axos(分佈式一致性算法)做爲分佈式系統的基石,一直都是計算機系統工程領域的熱門話題。Paxos 號稱是最難理解的算法,其實當真這麼困難麼?算法
X-Paxos 是阿里巴巴數據庫團隊面向高性能、全球部署以及阿里業務特徵等需求,實現的一個高性能分佈式強一致的 Paxos 獨立基礎庫。X-Paxos 具體有哪些優點,能給現有的系統帶來什麼樣的收益呢?sql
雖然 Paxos 的理論提出已經 17 年了,從第一個 Paxos 的工業實現到如今也已經 11 年了,可是直到近幾年,不管是頂級會議,仍是業內會議,與 Paxos 相關的文章和項目仍是層出不窮。數據庫
轉向業內,真正工業級的、獨立的 Paxos 基礎庫仍是至關的少見:後端
Google 並無開源任何 Paxos 基礎庫(連包含 Paxos 的項目都沒有開源過)。性能優化
Facebook 也沒有公佈過包含 Paxos 的產品。網絡
Apache 有 Zookeeper,可是其協議並不能支持一個高吞吐的狀態機複製,且並無提供獨立的第三方庫,可供快速接入。多線程
在 Github 上,能找到的 Paxos 的獨立庫,star 最高的是騰訊去年開源的 phxpaxos。架構
所以到目前爲止,業內還鮮有成熟可靠的,可供快速使用的獨立第三方的 Paxos 庫,開源的 Paxos 生態也還沒有成熟。併發
咱們的初衷並非要作一個 Paxos 的公共庫,X-Paxos 誕生於阿里巴巴的分佈式數據庫 AliSQL X-Cluster,但 X-Paxos 並不屬於 AliSQL X-Cluster。Paxos 是分佈式系統的基石,X-Paxos 可用於解決各類各樣的分佈式系統中的一致性問題。框架
所以在整個分佈式數據庫的設計之初,咱們就獨立設計了分佈式一致性協議模塊,並把它獨立爲 X-Paxos。X-Paxos 爲 AliSQL X-Cluster 解決了分佈式一致性問題,一樣能夠快速賦予其餘系統分佈式一致性能力。
分佈式一致性需求,並非 AliSQL X-Cluster 所特有的,不少系統都存在着高可用和強一致的需求,咱們把 Paxos 的能力獨立成一個基礎庫,但願可以把這個能力帶給其餘更多的系統。
例如,團隊內的同窗把 X-Paxos 融入到單機 KV 數據庫 RocksDB 中,快速實現了一個分佈式 KV 引擎。集團已有業務團隊把 X-Paxos 融入到業務存儲系統中,構建全新的分佈式強一致存儲服務。同時也正是 AliSQL X-Cluster,成就了 X-Paxos。Google 的論文《Paxos made live》中有一段話說的很好,大意是說:Paxos 從理論到現實世界的實現之間有巨大的鴻溝,在真正實現一個 Paxos 的時候,每每須要對 Paxos 的經典理論作一些擴展。
尤爲是在實現一個高性能的 Paxos 的時候,擴展點就更多了,能夠參考後文的功能加強和性能優化,這每每會致使真正的 Paxos 實現都是基於一個未被徹底證實的協議。這也就是傳說中,理論證實一個 Paxos 的實現,比實現這個 Paxos 還要難的緣由了。所以一個成熟的 Paxos 實現很難獨立產生,每每須要和一個系統結合在一塊兒,經過一個或者多個系統來驗證其可靠性和完備性。這也是爲何大部分紅熟的 Paxos 案例都是和分佈式數據庫相結合的,例如最先的 Paxos 實現(Chubby),當前的主要 Paxos 實現(Google 的 MegaStore、Spanner,AWS 的 DynamoDB、S3 等)。而 X-Paxos 正是依託於 AliSQL X-Cluster 驗證了其可靠性和完備性。
咱們的願景是但願可以提供一個通過實踐檢驗的,高度成熟可靠的獨立 Paxos 基礎庫。使得一個後端服務可以經過簡單的接入,就能擁有 Paxos 算法賦予的強一致、高可用、自動容災等能力。真正將晦澀難懂的 Paxos,變得平易近人,帶入千萬家。
X-Paxos 的總體架構
X-Paxos 的總體架構以下圖所示,主要可分爲網絡層、服務層、算法模塊、日誌模塊四個部分:
網絡層
網絡層基於阿里內部很是成熟的網絡庫 libeasy 實現。libeasy 的異步框架和線程池很是契合總體的異步化設計,同時咱們對 libeasy 的重連等邏輯進行了修改,以適應分佈式協議的需求。
服務層
服務層是驅動整個 Paxos 運行的基礎,爲 Paxos 提供了事件驅動,定時回調等核心的運行功能,每個 Paxos 實現都有一個與之緊密相關的驅動層,驅動層的架構與性能和穩定性密切相關。
X-Paxos 的服務層是一個基於 C++11 特性實現的多線程異步框架。常見的狀態機/回調模型存在開發效率較低,可讀性差等問題,一直被開發者所詬病。
而協程又因其單線程的瓶頸,而使其應用場景受到限制。C++11 之後的新版本提供了完美轉發(argument forwarding)、可變模板參數(variadic templates)等特性,爲咱們可以實現一種全新的異步調用模型提供了可能。
例如,下面是 X-Paxos 內實際的一行建立單次定時任務的代碼:
new ThreadTimer(srv_->getThreadTimerService(), srv_, electionTimeout_, ThreadTimer::Oneshot, &Paxos::checkLeaderTransfer, this, targetId, currentTerm_.load(), log_->getLastLogIndex());
以上一行程序,包含了定時器的建立,任意回調函數的設置,回調函數參數的轉發,並保證在回調觸發後(Oneshot)內存的自動回收。同時服務層支持嵌套回調,即在回調函數中再一次生成一個定時/即時任務,實現一個有限次的定時循環邏輯。
算法模塊
X-Paxos 當前的算法基於 unique proposer 的 multi-paxos [3] 實現,大量理論和實踐已經證實了基於 unique proposer 的 multi-paxos,性能好於 multi-paxos/basic paxos,當前成熟的基於 Paxos 的系統,大部分都採用了這種方式。
算法模塊的基礎功能部分本文再也不重複,感興趣的同窗能夠參考相關論文 [1,2,4]。
在基礎算法的基礎上,結合阿里業務的場景以及高性能和生態的需求,X-Paxos 作了不少的創新性的功能和性能的優化,使其相對於基礎的 multi-paxos,功能變的更加豐富,在多種部署場景下性能都有明顯的提高。
日誌模塊
日誌模塊本是算法模塊的一部分,可是出於對極致性能要求的考慮,咱們把日誌模塊獨立出來,並實現了一個默認的高性能的日誌模塊。
有極致性能以及成本需求的用戶,能夠結合已有的日誌系統,對接日誌模塊接口,以獲取更高的性能和更低的成本。這也是 X-Paxos 做爲高性能獨立庫特有的優點。
咱們結合普遍的業務場景,構建開放的生態:
1. 在線添加/刪除節點,在線轉讓 leader
X-Paxos 在標準 multi-paxos 的基礎上,支持在線添加/刪除多種角色的節點,支持在線快速將 leadership 節點轉移到其餘節點(有主選舉)。
2. 策略化多數派和權重化選主
目前,阿里集團及螞蟻金服的多地有中心的架構,不少應用因其部署的特色,每每要求它在未發生城市級容災的狀況下,僅在中心寫入數據庫,或調用其餘分佈式服務。
同時又要求在發生城市級容災的時候(同一個城市的多個機房所有不可用),能夠在徹底不丟失任何數據的狀況下,將寫入點切換到非中心。
而經典的 multi-paxos 並不能知足這些需求。經典理論中,多數派強同步之後便可完成提交,而多數派是非特定的,並不能保證某個/某些節點必定能獲得完整的數據,並激活服務。
在實際實現中,每每地理位置較近的節點會擁有強一致的數據,而地理位置較遠的節點,一直處於非強一致節點,在容災的時候永遠沒法激活爲主節點,這樣就形同虛設。
同時,當中心單節點出現故障須要容災的時候,每每須要將主節點就近切換到同中心的另一個節點。因爲應用在多地的部署每每是非對稱的緣由,出現單個 Region 全掛的時候,須要將主節點切到特定的 Region 內。
這些需求都須要 Paxos 在選主的時候,能夠由用戶指定規則,而經典理論中一樣沒有相似的功能,添加權重也須要保證 Paxos 的正確性。
X-Paxos 在協議中實現了策略化多數派和權重化選主:
基於策略化多數派,用戶能夠經過動態配置,指定某個/某些節點必須保有強一致的數據,在出現容災需求的時候,能夠當即激活爲主節點。
基於權重化選主,用戶能夠指定各個節點的選主權重,只有在高權重的節點所有不可用的時候,纔會激活低權重的節點。
3.節點角色定製化(Proposer/Accepter/Learner 的獨立配置)
在經典的 multi-paxos 實現中,通常每一個節點都包含了 Proposer/Accepter/Learner 三種功能,每個節點都是全功能節點。可是某些狀況下,咱們並不須要全部節點都擁有所有的功能。例如:
在經典的三個副本部署中,咱們能夠裁剪其中一個節點的狀態機,只保留日誌(無數據的純日誌節點,可是在同步中做爲多數派計算),此時咱們須要裁剪掉協議中的 Proposer 功能(被選舉權),保留 Accepter 和 Learner 功能。
咱們但願能夠有若干個節點能夠做爲下游,訂閱/消費協議產生的日誌流,而不做爲集羣的成員(不做爲多數派計算,由於這些節點不保存日誌流),此時咱們裁剪掉協議的 Proposer/Accepter 功能,只保留 Learner 功能。
固然還有其餘的組合方式,經過對節點角色的定製化組合,咱們能夠開發出不少的定製功能節點,即節約了成本,又豐富了功能。
4. Witness SDK
基於上節節點角色定製化中的單獨 Learner 角色的功能,引起了無窮的想象力。
Learner 角色,能夠抽象成一個數據流訂閱者(Witness Node),整個集羣中能夠加入無數個訂閱者,當有新的日誌被提交的時候,這些訂閱者會收到他關心的日誌流,基於訂閱者功能。
咱們可讓一個集羣很容易的實現下游訂閱消費,日誌即時備份,配置變動推送等等的功能。
所以咱們把 Learner 角色單獨封裝成了一個 SDK。基於這個 SDK,用戶能夠快速地爲本身的集羣添加,訂閱註冊,流式訂閱定功能;結合特定的用途打造一個完整的生態。
例如,日誌流 SDK 在 AliSQL X-Cluster 中打造的生態。以下圖,採用了 X-Paxos 也能夠利用 Witness SDK 快速實現分佈式系統和下游的其餘系統的對接,造成一個完整的生態。
咱們拿 MySQL 的日誌(binlog)備份來舉例:
普通方案。每隔固定時間 Tb,將 MySQL 生成的 binlog 文件備份到永久備份系統(OSS、S3 等)。RPO (Recovery Point Objective)爲 Tb。
SDK 方案。X-Paxos 支持由 SDK 訂閱增量日誌,備份系統只須要簡單的實現從 SDK 流到 OSS 流的對接,便可實現流式備份。RPO (Recovery Point Objective)爲 0。
除備份之外,Witness SDK 在下游流式訂閱(DRC)、自封閉高可用系統(X-Driver)、異步只讀備庫等方面都有實戰案例,更多的應用案例在不斷的添加中。
咱們一直堅信網絡延遲不該該影響吞吐。
Batching & Pipelining
Paxos 除了設計之初的強一致和高可用之外,其高性能也是相當重要的,尤爲是應用於 AliSQL X-Cluster 這種高性能分佈式數據庫的時候,對協議的吞吐,延遲都提出了很高的要求。
同時做爲可全球部署的分佈式一致性協議,在高延遲下的性能挑戰變得尤其重要。
X-Paxos 針對高延遲網絡作了大量的協議優化嘗試和測試,並結合學術界現有的理論成果 [5,6,7] 經過合理的 Batching 和 Pipelining,設計並實現了一整套自適應的針對高延遲高吞吐和低延遲高吞吐網絡的通訊模式。
極大的提高了 X-Paxos 的性能(對比見下節)。相似的優化在同類競品中還很是的罕見。
Batching 是指將多個日誌合併成單個消息進行發送;Batching 能夠有效的下降消息粒度帶來的額外損耗,提高吞吐。可是過大 Batching 容易形成單請求的延遲過大,致使併發請求數太高,繼而影響了吞吐和請求延遲。
Pipelining 是指在上一個消息返回結果之前,併發的發送下一個消息到對應節點的機制,經過提升併發發送消息數量(Pipelining 數量),能夠有效的下降併發單請求延遲。
同時在 transmission delay 小於 propagationdelay 的時候(高延遲高吞吐網絡),有效提高性能。
經推導可知 Batching(消息大小:M)和 Pipeling(消息併發:P)在以下關係下,達到最高吞吐 M/R * P = D。
其中 R 爲網絡帶寬,D 爲網絡傳播延遲(propagation delay,約爲 RTT/2)
X-Paxos 結合以上理論,經過內置探測,針對不一樣節點的部署延遲,自適應的調整針對每一個節點的 Batching 和 Pipeling 參數,達到總體的最大吞吐。
Pipeling 的引入,須要解決日誌的亂序問題,特別是在異地場景下,window 加大,加大了亂序的機率。X-Paxos 經過一個高效的亂序處理模塊,能夠對底層日誌實現屏蔽亂序,實現高效的亂序日誌存儲。
多線程,全異步的 Paxos 庫
因爲 Paxos 的內部狀態複雜,實現高效的單實例多線程的 Paxos 變成一個很是大的挑戰。不管咱們上面提到的 Github 中 star 最多的 phxpaxos,仍是 Oracle MySQL Group Replication 中使用的 xcom,都是單線程的實現。
phxpaxos 採用了單分區單線程,多實例聚合的方式提高總吞吐,可是對單分區的性能提高很是有限;而 xcom 是一個基於協程的單線程實現。單線程的 Paxos 實現,在處理序列化/反序列化,分發、發包等邏輯的時候都爲串行執行,性能瓶頸明顯。
X-Paxos 是徹底基於多線程實現的,能夠在單個分區 Paxos 中徹底的使用多線程的能力,全部的任務都有通用的 woker 來運行,消除了 CPU 的瓶頸。
依賴於服務層的多線程異步框架和異步網絡層,X-Paxos 除了必要的協議串行點外,大部分操做均可以併發執行,而且部分協議串行點採用了無鎖設計,能夠有效利用多線程能力,實現了 Paxos 的單分區多線程能力,單分區性能遠超競品,甚至超過了競品的多分區性能。
Locality Aware Content Distribution
基於 unique proposer 的分佈式系統存在的一個瓶頸點就是主節點是惟一的內容輸出源,當集羣存在大量節點的時候,主節點的大量網絡收發工做會致使主節點的負載過大,引起 CPU 和帶寬的瓶頸。
在全國/全球部署的時候,全部節點和主節點之間的直接通訊會形成跨 Region 之間的長傳/國際鏈路的帶寬佔用過大。
X-Paxos 是旨在解決全球分佈式強一致問題的 Paxos 獨立庫,在設計之初就考慮到了這個問題。
X-Paxos 在穩態運行時會感知各個節點之間的網絡延遲(物理距離),並造成級聯拓撲,有效下降主節點的負載,下降長傳鏈路的帶寬使用;而在有節點異常的時候,又會自動重組拓撲,保證各個存活節點間的同行的正常進行。
同時 X-Paxos 支持由業務來設定重組拓撲的規則,業務能夠根據本身 APP 的部署架構和延遲特性來針對性的設置拓撲重組規則。
可插拔日誌
X-Paxos 和現有的大部分 paxos 庫很大的不一樣點就是 X-Paxos 支持可插拔的日誌模塊。日誌模塊是 Paxos 中一個重要的模塊,它的持久化關係到數據的一致性,它的讀寫性能很大程度上會影響協議總體的讀寫性能。
當前大部分獨立 Paxos 庫都是內置日誌模塊,而且不支持插拔的。這會帶來兩個弊端:
默認的日誌模塊提供通用的功能,很難結合具體的系統作針對性的優化。
現有的系統每每已經存在了 WAL(Write Ahead Log),而 Paxos 協議中須要再存一份。這使得 a)單次 commit 本地須要 sync 2 次(影響性能);b)雙份日誌浪費了大量的存儲。
例如,phxpaxos 內置的日誌模塊採用的 LevelDB,做爲日誌系統其操做大量冗餘,無針對優化,性能堪憂。
同時採用 phxpaxos 的 phxsql 單節點須要既保存 binlog,又保存 Paxos log(在獨立的 phxbinlogsvr 中),嚴重影響了性能,浪費了存儲空間。
而採用 X-Paxos 的 AliSQL X-Cluster 直接改造了現有的 binlog 模塊,對接到 X-Paxos 的日誌模塊,單節點僅一份日誌,既下降了存儲,又提升了性能。
對於一個分佈式強一致協議來講,正確性是生命線。上文已經說起,一個分佈式強一致協議,很難完整的理論證實其正確性,再加上工程實現的問題,困難就更多了。
咱們從理論和工程兩方面用了大量的理論和技術手段來保證 X-Paxos 的正確性和完備性。
Jepsen
Jepsen 是開源社區比較公認的分佈式數據庫的測試框架。Jepsen 驗證過程包括 VoltDB、CockroachDB、Galera、MongoDB、etcd 在內的幾乎全部的主流分佈式數據庫/系統,檢驗出了很多的問題。
X-Paxos 完成了和 Jepsen 的對接,並驗證了各個分佈式數據庫已有的 case。
TLA+
TLA+ 是 Paxos 創始人、圖靈獎得到者 Leslie Lamport 發明的一種形式化規約語言。 TLA+ 專用於設計、建模和驗證分佈式併發系統。Amazon DynamoDB/S3/EBS 和 MicrosoftCosmos DB 都經過 TLA+ 的模型驗證發現了很多問題。
X-Paxos 目前已經經過了 TLA+ 的模型驗證。
隨機異常系統
咱們搭建了一套自動隨機異常驗證系統,能夠自動化驗證各類異常場景下的協議正確性和穩定性。驗證 X-Paxos 在模擬網絡丟包、閃斷、隔離,磁盤故障等狀況下的功能正確和數據一致。
異常回歸系統
X-Paxos 擁有一套異常 case 迴歸系統,對於曾經出現過或者預期的併發異常 case,都會加到異常 case 庫中,進行平常回歸驗證。同時異常 case 庫也在不斷的豐富中。
XCOM (MySQL Group Replication)
MySQL GroupReplication 是 MySQL 官方借鑑 Galera 的思想,在 MySQL 上構建分佈式強一致集羣的一個插件。
MySQL Group Replication 早期採用的分佈式協議是 CoroSync,它是由 Red Hat 開發的基於 Totem(The Totem Single-Ring Ordering and MembershipProtocol)[8] 協議開發的分佈式一致性協議庫。
因爲 Totem 算法自己存在的一些侷限性能緣由,從 MySQL 5.7.9 版本之後,官方採用了本身研發的基於類 Paxos(Mencius)[10] 的一致性協議庫 XCOM。
XCOM 是 MySQL Group Replication 的核心組件,稱爲 Group Communication Core[9]。咱們分析了 XCOM 的源碼,XCOM 內部是一個由純 C 語言編譯的核心模塊以及由 C++ 實現的 proxy 的系統。
純 C 模塊由單線程驅動,依賴協程實現任務調度。所以 Client(MySQL GroupReplication Plugin)必須用 TCP 鏈接向 XCOM 發送請求。
所以 XCOM 存在以下的不足之處:
單線程驅動,無多線程能力。架構決定,很難突破。
通訊流須要額外的一次 TCP 協議棧。在內存拷貝都要精細計算的應用中,線程間多一次網絡通訊很難接受。
XCOM 雖然實現了 Batching 和 Pipelining,可是其值均爲固定值,很難適應真實的場景。官方的文檔中也提到了這一點[9]。這也使得 MySQL Group Replication 在跨 Region 場景中性能很不理想(見 AliSQL X-Cluster 對比測試)。
phxpaxos (phxsql)
phxpaxos 是騰訊推出的基於 Paxos 協議的獨立庫,它和 MySQL 結合後推出了 phxsql 項目,也是基於 MySQL 實現的分佈式強一致 MySQL 集羣。
phxpaxos 可獨立用於其餘項目,是目前 Github 上 star 最多(1000+)的 Paxos 獨立庫。關於 phxsql 的細節本文再也不敘述,能夠參考(AliSQL X-Cluster 的競品分析部分),咱們這裏主要分析 phxpaxos。
phxpaxos 也是基於 multi-Paxos 實現的獨立庫,架構上採用單 Paxos 單線程設計,可是支持多 Paxos 分區以擴展多線程能力,這種擴展須要多數據進行提早分區。
所以 phxpaxos 的不足之處,以下:
單 Paxos 對象只支持單線程,可支持多 Paxos 對象,共享網絡層。
不支持 pipelining,在跨 Region 環境(高延遲)下,幾乎不可用。
多份日誌冗餘,基於 LevelDB 的日誌系統性能瓶頸。
性能對比
咱們仍是拿騰訊的 phxpaxos 做爲競品和咱們進行對比(XCOM 無獨立組件,可間接參考 MySQL Group Replication 和 AliSQL X-Cluster 的對比測試結果)。
咱們分別在 a) Region 內 3 節點部署 b) 3 個 Region 各一個節點部署調節下,以不一樣的請求大小進行壓測。
從上面兩個對比圖中能夠看到:
X-Paxos 的同 Region 性能是 phxpaxos 的 100 倍以上。
跨 Region 場景下 phxpaxos 幾乎不可用,而 X-Paxos 在 444Byte(sysbench insert 場景單請求大小),性能只有 3.5% 的降低,幾乎不影響吞吐。
現狀:目前 X-Paxos 一期已經發布上線。基於 X-Paxos 的集團數據庫團隊產品 AliSQL X-Cluster 已在集團內普遍使用。X-Paxos 和業務系統結合打造的分佈式服務也相繼落地上線。
將來:Paxos 是分佈式系統的基石,即便是近幾年,學術界關於 Paxos 的文章,新的演進方向一直在不斷的涌現,咱們的 X-Paxos 也會不停的發展,以更好的適應集團內外的需求。
將來主要的發展方向以下:
高效率,多分區支持。基於新的異步框架,實現一個深度底層共享的多分區 Paxos。
多節點強一致讀。經典的 multi-paxos 只有在 leader 上才能提供強一致讀,spanner和業界都有一些在多節點上提供強一致讀的方案,但仍是有比較明顯的缺陷。
參考文件:
[1]The part-time parliament [2]The Chubby lock service for loosely-coupled distributed systems [3]Paxos Made Simple [4]Paxos Made Live - An Engineering Perspective [5]Everything You Ever Wanted to Know About Message Latency [6]Adaptive Batching for Replicated Servers [7]Tuning Paxos for high-throughput with batching and pipelining [8]The Totem single-ring ordering and membership protocol [9]Group Replication: A Journey to the Group Communication Core [10]Mencius: Building Efficient Replicated State Machines for WANs |
10多年 Linux C/C++ 底層研發經驗,數據庫內核研發經驗。長期從事 MySQL 內核研發,分佈式數據庫研發工做。同時做爲數據庫內核負責人屢次參加阿里巴巴雙十一購物節。AliSQL 項目主要開發人員,主導阿里的分佈式強一致協議 X-Paxos 開發工做。