首發於 2018-12-08,修改於 2021-12-12。
1 - ZooKeeper的主從機制
在絕大部分通過主從實現高可用的系統中,Leader == Master,Follower == Slaver。
集群中的各個節點都會嘗試注冊為 leader 節點,其他沒有注冊成功的則成為 follower(隨從)節點。
這些 follower 節點通過 watcher(觀察者)監控着 leader 節點:
—— ZooKeeper 內部通過心跳機制來確定 leader 的狀態,一旦 leader 節點出現問題,集群內部就能立即獲悉並迅速通知其他 follower 節點來選出新的 leader。
2 - 什么是 ZooKeeper 的腦裂
2.1 腦裂現象的表現
ZooKeeper 集群中,各個節點間的網絡通信不良時,容易出現腦裂(split-brain)現象。
1)集群中的部分 follower 節點監聽不到 leader 節點的心跳,就會認為 leader 節點出了問題;
2)這些監聽不到 leader 節點心跳的 follower 節點就會選舉出新 leader 節點;
3)新的 leader 和舊 leader 節點 和各自的 follower 節點組成多個小集群。
—— 一個集群中有多個 leader 節點,這就是腦裂現象。
2.2 為什么會出現腦裂
設想這樣一種情況:
① 集群中網絡通信不好,導致心跳監測超時 —— follower 認為 leader 節點由於某種原因掛掉了,可其實 leader 節點並未真正掛掉 —— 這就是假死現象。
② leader 節點假死后,ZooKeeper 通知所有 follower 節點進行新的選舉 ==> 某個 follower 節點升級為新的 leader —— 此時集群中存在2個leader節點。
③ 此時 ZooKeeper 需要將新 leader 節點的信息通知給所有 follower 節點,還要通知到所有的 client(比如 Kafka 集群中的 Kafka 節點就是一個 client),這個過程由於網絡等因素的影響,消息到達肯定存在不同程度的延遲。
④ 如果部分 client 獲得了新 leader 節點的信息,而部分沒有獲得,恰好此時 client 向 ZooKeeper 發起讀寫請求,ZooKeeper 內部的不一致就會導致:部分 client 連接到了新的 leader 節點,而部分 client 連接到了舊的 leader節點 —— 服務中出現了2個leader,client 不知道聽誰好,就像1個大腦被分裂成2個,很形象吧O(∩_∩)O
3 - ZooKeeper如何解決"腦裂"
3.1 3種可行的思路
(1) Quorums(ˈkwɔrəm,法定人數)
通過設置法定人數,進而確定集群的容忍度,當集群中存活的節點少於法定人數,集群將不可用。比如:
3個節點的集群中,Quorums = 2 —— 集群可以容忍 (3 - 2 = 1) 個節點失敗,這時候還能選舉出 leader,集群仍然可用;
4個節點的集群中,Quorums = 3 —— 集群同樣可以容忍 1 個節點失敗,如果2個節點失敗,那整個集群就不可用了。
(2) Redundant communications(冗余通信)
集群中采用多種通信方式,防止一種通信方式失效導致集群中的節點無法通信。
(3) Fencing(隔離,即共享資源)
通過隔離的方式,將所有共享資源隔離起來,能對共享資源進行寫操作(即加鎖)的節點就是 leader 節點。
3.2 ZooKeeper 的做法
ZooKeeper 默認采用了Quorums 的方式:只有獲得超過半數節點的投票,才能選舉出 leader。
這種方式可以確保要么選出唯一的 leader,要么選舉失敗。
ZooKeeper 中 Quorums 的作用:
① 指定集群中選舉 leader 所需的最少節點數,保證集群可用;
② client 的數據被安全保存到集群中所需的最少節點數,一旦這些節點保存了數據,客戶端將被通知數據已經安全保存,可以繼續其他任務 —— 基於最終一致性,集群中剩余的節點最終也會保存相關的數據。
ZooKeeper的寫也遵循quorum機制,因此得不到大多數支持的寫是無效的。
3.3 ZooKeeper 的具體解決思路
假設:leader 發生了假死,followers 選舉出了一個新的 leader。
當舊的 leader 復活並認為自己仍然是 leader,它向其他 followers 發出寫請求時,會被拒絕。
—— 因為 ZooKeeper 維護了一個叫 epoch 的變量,每當新 leader 產生時,epoch 就會遞增,followers 如果確認了新的 leader,同時也會知道其 epoch 的值 —— 它們會拒絕所有 epoch 小於現任 leader 的 epoch 的舊 leader 的請求。
注意:仍然會存在有部分 followers 不知道新 leader 的存在,但肯定不是大多數,否則新 leader 將無法產生。
參考資料
版權聲明
出處:博客園-瘦風的南牆(https://www.cnblogs.com/shoufeng)
感謝閱讀,公眾號 「瘦風的南牆」 ,手機端閱讀更佳,還有其他福利和心得輸出,歡迎掃碼關注🤝
本文版權歸博主所有,歡迎轉載,但 [必須在頁面明顯位置標明原文鏈接],否則博主保留追究相關人士法律責任的權利。