braft初探


接上一篇《brpc初探》。

什么是RAFT

看內部一個開源項目的時候,一開始我以為他們自己實現了raft協議。但是看了代碼之后,發現用的是braft。因為在我們自己bg里一直在提paxos,bg開源的東西很多也是基於paxos。但是實際上paxos是什么我並不清楚,只知道是個一致性協議。關於paxos和raft的關系,可以看braft的文檔(這里贊一下braft的文檔,寫得非常高質量):

RAFT是一種新型易於理解的分布式一致性復制協議,由斯坦福大學的Diego Ongaro和John Ousterhout提出,作為RAMCloud項目中的中心協調組件。Raft是一種Leader-Based的Multi-Paxos變種,相比Paxos、Zab、View Stamped Replication等協議提供了更完整更清晰的協議描述,並提供了清晰的節點增刪描述。

Raft作為復制狀態機,是分布式系統中最核心最基礎的組件,提供命令在多個節點之間有序復制和執行,當多個節點初始狀態一致的時候,保證節點之間狀態一致。系統只要多數節點存活就可以正常處理,它允許消息的延遲、丟棄和亂序,但是不允許消息的篡改(非拜占庭場景)。

Raft可以解決分布式理論中的CP,即一致性和分區容忍性,並不能解決Available的問題。其中包含分布式系統中一些通常的功能:

  • Leader election.
  • Replication and recovery.
  • Snapshot and log compaction.
  • Membership management.
  • Fully concurrent replication.
  • Fault tolerance.
  • Asymmetric network partition tolerance.
  • Workaround when quorate peers are dead.

通過RAFT提供的一致性狀態機,可以解決復制、修復、節點管理等問題,極大的簡化當前分布式系統的設計與實現,讓開發者只關注於業務邏輯,將其抽象實現成對應的狀態機即可。基於這套框架,可以構建很多分布式應用:

  • 分布式鎖服務,比如Zookeeper
  • 分布式存儲系統,比如分布式消息隊列、分布式塊系統、分布式文件系統、分布式表格系統等
  • 高可靠元信息管理,比如各類Master模塊的HA

overview: https://github.com/brpc/braft/blob/master/docs/cn/overview.md

Paxos主要包括兩個組件:Proposer和Acceptor,其中Proposer主動發起投票,Acceptor被動接收投票,並存儲提案值。在實際系統中,每個Paxos Server都包含這兩個組件。

關於paxos和raft還有專門的文檔:

https://github.com/brpc/braft/blob/master/docs/cn/paxos_protocol.md

https://github.com/brpc/braft/blob/master/docs/cn/raft_protocol.md

在構建分布式存儲系統過程中,一般會有Master來實現一些節點加入離開、副本修復、負載均衡以及業務相關的元信息CURD。對於這些Master模塊的HA百度做過很多嘗試,比如keepalived、QJM等,一直沒有比較理想的解決方案。
在2015年中的時候,我們想到用Raft來解決這個問題,Raft的復制狀態機能夠解決高可用的問題,選主和節點變更也非常方便,不用再依賴ZK。

braft是解決復制狀態機問題,brpc是解決模塊間RPC通信問題。braft中Raft協議的互通直接使用brpc實現,runtime使用了bthread,因此braft編譯需要依賴brpc,從這點來看braft和brpc有一定的綁定關系。
但是從另一個角度來看,braft中核心的是協議狀態機比如log、snapshot、configuration這些東西的抽象和實現,協議RPC只是其中一環,做一層transport抽象也可以比較容易的替換為其他的coroutine based protobuf RPC框架,對於非coroutinebased protobuf RPC來講,braft只能用類似logcabin中pthread同步RPC,這樣就喪失了多復制組支持的特性,RPC的回調改造成本就比較高了。

做基礎架構工作,第一要做的是時刻關注學術界和企業界的發展,多與同行交流來獲取業界的發展動態,不斷的提高自己的眼界,有助於做出更好的系統設計。
在大型系統設計的時候需要能夠構建清晰的模型,模塊怎么划分怎么交互。模型清晰之后就是系統的詳細設計,分布式系統中有很多時序相關的東西和問題,不能像單機一樣去調試,所以在設計階段就要把系統中的每個細節都想清楚,能夠推演系統的各個流程。思考系統中各種race condition,對於這些race condition首先要量力而行,避免過早設計、過早優化導致項目延期;解決問題過程中,如無必要盡量使用簡單的方案,復雜方案的實現也會帶來隱患;對於低概率問題或者是高成本問題,即使不解決也需要做到心中有數。
架構改進要數據說話,通過各種工具和日志等分析出系統架構中最棘手的三個問題,然后針對這些問題制定相應的改造方案。這里需要注意的是方案設計不僅僅是提出一個全新的解決方案,還需要考慮如何把系統從當前方案遷移到新的方案,同時確保遷移過程是盡可能的平滑無損。
對於重大版本在開發測試完成之后,需要做幾次上線演練,記錄並修正演練過程中的非預期問題。這樣經過幾次迭代之后,系統的問題就會逐步收斂,當收斂到一定階段之后,如果依然有一些比較大的問題難以修復,這個時候根據人力條件判斷是繼續在現有條件下規避問題,還是整體重構或者是部分重構來解決問題。

https://baijiahao.baidu.com/s?id=1603689359064649109

關於測試的論述也對我很有啟發。

幾乎所有的框架、模塊、類庫, 都會把高性能作為最重要的標簽之一(當然, braft也不例外)。但是常常開發者對於性能理解只是停留在吞吐或者QPS的數字表面,性能測試變成了想方設法刷數字的游戲,而不考慮場景是否符合實際應用場景。常見的『提升性能數字』的方法有以下兩類:

Batch: 系統主動等request數量達到一定數量或者等一個超時時間, 合成一個request發給后端系統, 取決於batch_size / request_size 的值, 能將"QPS"提升幾十~幾百倍. (這點后面再詳細解釋)。
Client不限制的異步發送: 這樣能讓系統一直處於高負載狀態,不存在任何的等待,規避了一些系統調用和線程同步開銷。
這些設計雖然能跑出不錯的benchmark數據,但是完全偏離了實際的應用場景。以batch為例, batch的問題在於本質上並沒有去指導如何提升系統的QPS。在性能測試中,並發度通常很高,會有源源不斷的請求進來,所以每個請求並不需要等待多長時間就能滿足batch size的條件, 然而在真實場景中,並發度並沒有這么高,這樣會導致每個請求都必須要『等待』一個設定的值, latency無法達到最優解。而這時候工程師往往會沉浸在優化超時、batch size等調參工作,從而忽略了分析系統瓶頸這類真正有意義的事情。另外硬件性能的逐漸提升,網絡和磁盤本身的延遲越來越短, 這套機制無法兼顧低負載下的延遲和高負載的吞吐。

在braft中,我們主要采用了以下幾點方法來提高的性能:

  • 數據流是全並發的, leader寫本地磁盤和向follower復制數據是完全並發的。
  • 盡可能的提高局部性,充分發揮不同層面的cache的作用
  • 盡可能隔離不同硬件的訪問,通過流水線的形式提高吞吐
  • 盡可能的降低鎖臨界區大小, 關鍵路徑上采用lock-free/wait-free算法.

https://github.com/brpc/braft/blob/master/docs/cn/benchmark.md


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM