在分布式領域,始終都要面臨的乙個挑戰就是:資料一致性
。它是指資料在各個機器節點上流轉的時候,如何保證任一時刻資料都是正確並且最新的。為此,萊斯利·蘭伯特(leslie lamport)在2023年提出了一種實現演算法,也就是著名的paxos。如今它是業界公認此類問題的最有效解。雖然paxos在理論界得到了高度認可,但是卻給工程界帶來了難題。因為這個演算法本身比較晦澀,並且抽象,缺少很多實現細節。這讓許多任務程師大為頭疼。天無絕人之路。幾十年後,希望的曙光出現了。來自史丹福大學的兩位仁兄 diego ongaro 和 john ousterhout 在「in search of an understandable consensus algorithm (extended version)」一文中正式引入 raft。並在**開篇就表明raft是為解決paxos難以理解和實現的問題而提出的。從此,raft一炮走紅。
raft 演算法的工作流程主要包含五個部分:
領導選舉(leader election):在集群初始化或者舊領導異常情況下,選舉出乙個新的領導。
日誌複製(log replication): 當有新的日誌寫入時,領導能把它複製到集群中大多數節點上。
集群成員變更(cluster membership changes): 當集群有擴容或者縮容的需求,集群各節點能準確感知哪些節點新加入或者被去除。
日誌壓縮(log compaction): 當寫入的日誌檔案越來越大,重啟時節點回放(replay)日誌的時間將無限延長,並且新節點加入集群時傳送日誌檔案也會無限拉大。需要定期對日誌檔案進行重整壓縮。
讀寫一致性(read/write consistency): 客戶端作為集群的外部元件,當乙個客戶端寫入新資料時,能保證後續所有客戶端都能讀到最新的值。
從上面可以看出,raft 演算法涵蓋的內容很多。如果一條條逐個講解,對於乙個初學者來說,無異於「一口吃下乙個胖子」,這顯然不切實際,也會讓人淹沒在細節的海洋中,失去對演算法的全域性認識。所以本文採用「突出主要問題,忽略其次細節」的方法先讓大家對其最核心的部分,領導選舉和日誌複製有乙個深入理解。
理解乙個演算法,最重要的是要知道如此設計的正確性。學習演算法的思想,才能真正理解,繼而分享和交流。上來就講實現細節,很難產生共鳴。
那怎麼論證raft的正確性呢?要科學地論證一件事,一般有兩種方法。
使用精巧的數學方程推導。這是最嚴謹的方式。
使用歸納假設推理。通過一步步邏輯推理最終歸納出結論。
本文採用第二種方式,也是raft**的論述推理形式。
raft為了簡化paxos的複雜性,提出了強領導模式。它是指在乙個正常執行的raft集群中,有且只有乙個leader,並且所有的寫入操作都必須通過leader來全域性控制。現在我們來做一道題:
假設raft集群有乙個領導,這個領導執行在最理想的環境下,就是說它永遠正常執行,並且網路通暢。請驗證在這個假定條件下raft的正確性。之前談到,raft是為了解決集群中資料一致性而提出的。當外部client進行乙個寫入操作(假定這個寫入是乙個賦值操作x=4)的時候,raft要保證這個寫入資料的一致性。需要說明的是:
這裡的一致性是指集群內部資料的一致性,也可以說是內部達成的共識,對於外部client暫不做要求,後文會提到client的一致性
。
其實資料一致性展開來講,是有幾層語義的:
資料的寫入順序要保持一致。否則可能出現很多不預期的情況,比如:舊值覆蓋新值。先刪後增變成先增後刪,資料消失了
對成功寫入的資料供認不諱。如果x=6被集群表明寫入成功,那麼集群各節點都應該認可並接受這個結果,而不會出現某些節點不知情的情況。
資料寫入成功保證持久化的。如果集群表明資料寫入成功,資料卻沒落盤。這時宕機了,那麼資料就丟失了。
現在我們來看看在領導永不掛機這一假定條件下,raft的做法。
我們對於資料一致性的三個方面進行了分析,發現raft都能很好的支援。這就能證明:在假定領導永不宕機的前提下,raft是能夠保證集群資料一致性的。
常言道,理想很豐滿,現實很骨感。在現實世界執行的計算機,其所處環境非常複雜。據統計,在乙個大型資料中心裡,每天都會有機器宕機,網路抖動。像磁碟壞道,網線老損,網絡卡降速等硬體問題也會時有發生。而磁碟容量不足,系統超載等軟體問題更是頻發。所以乙個程序永遠正常執行是不可能的。所以對於raft集群來說,leader一定會存在非正常執行的情況。那這個時候,raft是怎樣保證資料的一致性呢?
要回答這個問題,其實是要拆解成兩個子問題。首先是如何發現leader處於非正常執行狀態。在raft中,leader為了鞏固自己的領導地位,會定期向集群中其他節點傳送心跳,表明自己還活著。
而其他節點會維持乙個心跳超時時間(heartbeat timeout)
,如果在這個時間段內沒有如期收到leader的心跳,那麼該節點會認為leader處於非正常服務狀態。而這個時候,leader的真實情況對於該節點來說其實是未知,leader有可能確實掛掉了,也可能是系統負載高導致leader不響應卡死,還有可能是網路出現了抖動,訊息傳送延遲。
上一小節我們論證了在leader正常執行時,raft能保證集群的資料一致性。那麼在leader非正常運**況下,如果能選舉出乙個leader,不就能繼續保證資料一致性嗎。的確,raft就是這麼幹的。
raft規定:當集群中任意非leader節點的選舉時間超時,它能夠自行發動一輪leader投票選舉,設法讓自己成為leader。這裡需要宣告的是,raft把集群節點劃分成三種角色,分別是領導者(leader)、跟隨者(follwer)、候選者(candidate)。其中follower是被動接受來自leader的心跳和寫入日誌請求。candidate是能夠發起新一輪leader投票選舉的角色,它是由follwer發現心跳超時後,自動轉換而來。下圖詳細描述了節點在各角色之間轉換的觸發條件。
回到剛才話題,當candidate發起新一輪選舉時,應該基於什麼策略去選擇合適的leader呢?換句話說,應該選舉誰作為leader可以保證資料的一致性。raft規定:leader上已提交的日誌是不可以被覆蓋或更新的。
當乙個leader由正常變成非正常的那一時刻,它應該擁有集群中最新最全的日誌,如果我們能保證當選新leader的candidate節點的日誌盡可能和前leader的日誌一樣新,那麼這樣就不會丟失任何資料,會和之前集群日誌狀態一模一樣。當然這是最理想情況,實際很難做到。我們知道:已提交的日誌是會通知客戶端寫入成功的。如果已提交的日誌不能存在於新的leader中,那客戶端會很困惑,明明提示寫入成功,結果再次查詢卻找不到資料,這樣資料一致性就無法保證,所以新的leader要保證至少包含所有已提交的日誌。
那這個要如何做到呢?raft規定:candidate選舉時,只有自己log列表中最新日誌的log index和term與集群大多數節點一樣或者更大的時候,才能提公升自己為leader
。這裡出現了乙個新的術語,叫任期(term),也就是日誌列表圖中每個方塊內頂部居中的數字,它表示當前leader所處的任期號,每個leader在位的時候都有乙個唯一的任期號,並且保證任期內不可變。而新leader會對term進行自增。從整個過程看,term是乙個非嚴格單調遞增的整數值。回到問題討論,有人可能會疑惑這個為什麼就能保證新leader包含所有已提交日誌。道理很簡單,因為所有被判定為已提交的日誌必須在集群大多數節點中持久存在,而要推選為新leader的candidate的日誌至少要和集群中大多數節點一樣新,兩個多數派節點的集合必然存在至少乙個節點的交集,那麼這個節點既有所有已提交日誌,又能保證新leader至少和它一樣新,也就能推論出新leader至少擁有所有已提交的日誌
。這個推理可能有點繞,可以好好想想。
上面的推論,保證了leader在非正常運**況下,推選出的新leader至少擁有所有已提交的日誌,從而保證資料一致性。心細的讀者可能會問,那集群在舊leader異常和新leader選舉出來之前這段時間,該怎麼保證資料一致性呢?其實這個時候,集群處於「群龍無首」的狀態,而raft規定:一切寫入操作必須由leader管控
,所以這段時間客戶端的寫入會被告知失敗或者進行不斷重試。這裡其實一定程度上犧牲了集群的可用性來保證一致性。然而就像cap定理
告訴我們的,分布式系統不能既保證一致性c,又保證可用性a。而raft集群選擇了c和p,也就一定程度失去了a。
我們在假設leader正常執行的前提下,證明了raft能保證資料一致性。而在leader非正常執行的情況下,同樣證明了它能保證資料一致性。所以綜上,raft演算法能保證集群的資料一致性。
參考引用
leslie lamport. the part-time parliament. acm transactions on computer systems, 16(2):133–169, may 1998.
diego ongaro,john ousterhout.in search of an understandable consensus algorithm(extended version)
分布式一致性演算法Raft
我們先來看乙個例子 我們有乙個單節點node,這個節點可以是資料庫,也可以是一台伺服器,當client向node傳送data時,x節點收到data,記錄下來 由此可見對於單個節點,一致性是很容易實現的。然而對於多個節點,我們如何來實現一致性,這就是分布式一致性的問題。raft就是乙個實現分布式一致性...
分布式一致性協議Raft 案例剖析
中我們成功論證了raft保證集群資料一致性的問題。然而現實世界是非常複雜的,任何情況都可能發生。那麼對於各種異常場景raft集群究竟如何應對的呢?文章的同學可以先看一下,這篇相當於上篇的加強補充篇。在乙個集群中,如果發生了網路分割槽,會不會出現兩個leader導致資料不一致呢?上圖中展示了由5個藍色...
Raft一致性協議
什麼是raft協議?我們應當知道,分布式儲存系統通常通過維護多個副本來進行容錯,提高系統的可用性。要實現此目標,就必須要解決分布式儲存系統的最核心問題 維護多個副本的一致性。raft協議就可以完成這個操作。為什麼用raft?除了raft,還有很多協議可以實現這個功能,比如說 兩階段提交協議,三階段提...