Consul實現原理系列文章1: 用Raft來實現分佈式一致性

工作中用到了Consul來做服務發現,之後一段時間裏,我會陸續發一些文章來講述Consul實現原理。在前一篇文章中,我介紹了Raft算法。這篇文章會講講Consul是如何使用Raft算法來實現分佈式一致性的。

Consul中的Raft

只有以server模式運行的Consul節點,纔會被認爲是Raft節點集的一部分。所有的client節點會把收到的請求轉發到server節點中。這麼設計的原因主要是出於性能方面的考慮:節點集中的個數越多,那麼法定個數的值也就越大,這會導致leader節點可能需要等待數百個follower節點對一條log entry的agree信息。

在開始的時候,單個Consul server進入到bootstrap模式,這種模式允許它把自己選舉爲leader。當leader被選舉出來之後,別的server就可以被加入到節點集中,從而保障了一致性和安全性。最終,當最初的幾臺server被加進來後,bootstrap模式可以被關閉。

consul server加入節點集之後,他們會知道哪臺機器是當前的leader。當一個RPC請求到達一臺非leader server上時,這個請求會被轉發到leader上。如果這個請求是一個查詢類型(只讀),leader會基於現在的狀態機生成結果。如果這個請求是一個事物類型的請求(會修改狀態),leader會生成一個新的log entry,並用Raft的方法去處理它。當這個log entry被提交併且被應用到狀態機上時,這個事物就算完成了。

Raft會把log entry複製到多臺機器上,因此網絡延遲對於性能的影響很大。因爲這個原因,每個數據中心選出一個獨立的leader並且維護一份不相交的節點集。數據通過數據中心的方式做分割,因此每個leader只對自己這個數據中心內的數據負責。當一個請求到達一個數據中心,這個請求會被轉發到正確的leader那裏。這種設計下,我們可以做到低延遲事物以及高可用,而不用犧牲一致性。

一致性模式

儘管所有的log entry的寫入都會通過Raft來實現,讀取卻要靈活的多。爲了支持開發者可能需要的多種權衡取捨,Consul對於讀取,提供了三種不同的一致性模式。

這三種模式是:

default

Raft用到了leader約期的概念,意思是,在一個時間窗口中,leader認爲自己的角色是穩定的。但是,如果leader節點與別的節點被分隔,即發生所謂“腦裂”現象,那麼會有一個新的leader節點被選舉出來。舊的leader節點將不能提交任何新的log entry, 但是如果它提供了對數據的讀取,那麼客戶端讀到的這些值可能是過期的。

默認模式是基於leader約期的,因此客戶端可能讀到過期的值。但是這種模式是對讀取速度和一致性的一種取捨,犧牲了某些情況下的強一致性,以換取更高的讀取速度。

consistent

這種模式是強一致性模式。這種模式要求leader節點每次做讀和寫操作時都要與法定個數的節點去確認自己仍然是leader。 犧牲讀的速度,保障了強一致性。

stale

這種模式允許任何Consul server向外部提供讀取操作,無論它是不是leader節點。
這種模式特別快,但是讀到過期數據的可能性非常大。這種模式允許在沒有leader節點的情況下對讀請求做出相應,儘管實際上這時候Raft集羣已經是處於不可用狀態了。

參考:

https://www.consul.io/docs/internals/consensus.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章