PacificA 一致性協議解讀
公司資料庫的一致性協議用的是 PacificA,相信更多人對 raft 比較了解(畢竟是許多大學欽定的教學演算法,不曾了解過的可以看這裡 快速理解一致性協議 raft),這篇文章寫給懂 raft 的讀者。
PacificA 的 paper 在 08 年左右發出來的,比 Raft 早了 6,7 年。
在 PacificA 論文中,他們強調該演算法使用範圍是 LAN (Local Area Network),講白了就是對跨機房不友好。
不管是 ZAB,Raft,還是 PacificA,都是基於實用主義,把 log replication 和 leader election 分開,不像 paxos,把兩個問題合在一起想。
log replication
日誌複製流程與 raft 相似:每條日誌具有一個序列號(serial number),primary 複製日誌給 secondaries,secondary 接收到後返回 ack。
唯一不同的是,PacificA 要求收到所有節點的 ack 後,該請求才算提交,而在 raft 中,只需過半節點(quorum)即可提交。這也是該演算法不利跨機房的原因,但這種限制很大程度上能夠簡化協議。
leader election
一般高可用系統會用 zk/etcd 選主,而 zk/etcd 作為管理者本身,則需要用複雜的一致性協議來選主。PacificA 作為一個一致性協議另闢蹊徑,不守套路,選擇直接用 zk/etcd(用論文的說法叫 global configuration manager)來做選主。
一個一致性協議實現選主的方法是使用另一個一致性協議,這算是一個亮點。因為 zk/etcd 更多是針對元數據存儲做的系統,需要做普通數據分散式存儲的時候,PacificA 就有其意義了。換句話說,PacificA 只是保障普通數據高可用的,不會搶佔其他一致性協議的市場,它們是互補的關係。
PacificA 中 primary 與 secondaries 之間會使用心跳探活(論文里把 心跳 叫 Beacon )。與 Raft 類似的,secondary 探測不到 primary,就會向 configuration manager 申請換主。
PacificA 的 leader election 以 membership reconfiguration (成員變更)的方式來進行,這點很不一樣,因為 reconfiguration 在其他一致性協議里是一個比較難的事情,一般不輕易做。下面細講。
reconfiguration
由於有 configuration manager 的幫助,reconfiguration 變得比較簡單:向 zk 做一次 compare-and-swap 原子配置更新即可。
理論上這種方式可以輕鬆做到一次性變更多個成員(相比起 raft 要簡單許多)。
上面說到,secondary 探測不到 primary,就會向 configuration manager 申請換主,做法就是要求讓 primary 退群;而 primary 探測不到 secondary 時,日誌複製無法進行下去,這時 primary 也會申請讓 secondary 退群。
這裡很顯然的一個問題是 secondary 和 primary 互不相通的時候,會互相讓對方退群,造成一敗俱傷局面。PacificA 在這裡做了一個約定:primary 總會先於 secondary 讓對方退群。做法也很簡單,讓 primary timeout < secondary timeout 即可。
alternative
論文里雖然用組內心跳(primary 與 secondaries 之間的 heartbeat)來判活,但我們可以想,這不是必須的:
分散式系統里,每個節點通常會與一個中心資源管理器做心跳,一旦節點掛了,資源管理器就會找一台空閑機器新開節點。
在 PacificA,資源管理器可以作為 configuration manager,同時由於它能夠做心跳探活,組內心跳則可以直接省去。換句話說:
資源管理器看到 primary 失活,則進行換主,看到 secondary 失活,則令其退群,primary 和 secondary 之間沒有任何心跳。
在節點數較小的場景下,讓資源管理器做成員心跳不存在什麼壓力。
group check
雖然 primary 和 secondaries 之間可以沒有組內心跳,但是絕對不能沒有狀態同步。
首先 commit point 需要同步。secondary 在收到 commit point 之後,才能夠讓這部分已提交日誌被清理。
其次當前 term / ballot 和當前的 leader / primary 都需要同步。
另外事實上,需要組內同步的可能還包括一些應用相關的狀態。在 XiaoMi/pegasus 中,這一負責組內同步的 rpc 被稱為 group check。我們也用它同步熱備份時的備份點。
在 Raft 中,group check 和 heartbeat 的功能被組合在一起,避免長時間無寫請求時,節點間狀態無法同步。
reconciliation
換主的時候一個問題是新 primary 需要把尚未提交的日誌項提交了,算是完成舊 primary 的未竟之事。這個過程叫做 reconciliation。
Implementation
眾所周知 Raft 沒有講如何做日誌存儲的方案,儘管大家看了 logcabin 的 SegmentedLog 以後都知道大概怎麼做了。PacificA 在論文里講了這個問題,因為 PacificA 的 log 也需要考慮 overwriting,log compaction (checkpoint) 。不過一些相關點基本以前在 Raft 里講過了,neverchanje/consensus-yaraft,這裡就不再贅述。
推薦閱讀:
※快速打造分散式深度學習訓練平台
※利用DB實現分散式鎖的思路
※素描單元化
※論文筆記:[SRDS 2004] The Phi Accrual Failure Detector
※閱讀筆記:Scaling Memcache at Facebook
TAG:分散式系統 |