集羣中的 server 分爲三種角色:leader
, follower
, observer
。html
observer
是配置zoo.cfg
明肯定義的,角色leader
在一個zookeeper集羣中有且只能有一個,是經過內部的選舉機制臨時產生的。leader
是集羣中最重要的角色。負責響應集羣的全部對Zookeeper數據狀態變動的請求。它會將每一個狀態更新請求進行順序管理,以便保證整個集羣內部消息處理的 FIFO,遵循了順序一致性(Sequential Consistency)。
leader
內部維護 session ,來自客戶端的鏈接和斷開鏈接,都會被統一follower
或 observer
轉發給leader
處理。leader
內部維護單調遞增的 Zxid(ZooKeeper Transaction Id
),針對客戶端鏈接,斷開鏈接,節點的寫操做都會分配一個全局惟一的Zxid,同時這些操做是原子性的,而且是嚴格順序性的,遵循ZAB
原子廣播一致性協議完成事務(transaction)操做。若是客戶端的全部寫操做,都會被 follower
統一轉發給leader
處理。follower
具備選舉權。負責提供給客戶端讀寫服務,須要響應leader
的提議observer
沒有選舉權。主要提供給客戶端讀服務,不提供寫服務,也不須要響應leader
的提議。也不須要日誌文件,由於沒有寫服務,沒有持久化的須要。LOOKING
,競選狀態。FOLLOWING
,隨從狀態,同步leader
狀態,參與投票決策提案。OBSERVING
,觀察狀態,同步leader
狀態,不參與投票決策提案。LEADING
,領導者狀態,發起正常消息的提案。zookeeper中的znode數據都是在內存中優先維護和提供讀服務,當事務被提交以及最終提交都會持久化到磁盤的日誌文件中。node
Zookeeper 在內部網絡中如何實現兩兩鏈接的?算法
這裏暫且使用 10.0.2.30,10.0.2.31,10.0.2.32,10.0.2.33 替代 node1,node2,node3,node4,並依次啓動 zookeeper。shell
zoo.cfg
配置文件server.1=10.0.2.30:2888:3888 server.2=10.0.2.31:2888:3888 server.3=10.0.2.32:2888:3888 server.4=10.0.2.33:2888:3888
依次使用 netstat
查看網絡鏈接狀況apache
能夠看出來 node1做爲服務節點,由 node2,node3,node4 經過 3888端口創建鏈接進來。
node1 做爲客戶端鏈接 node3 (目前node3是leader
) 的2888端口。編程
能夠看出來 node2做爲服務節點,由 node3,node4 經過 3888端口創建鏈接進來。
可是 node2 做爲客戶端鏈接node1的3888端口。
node2 做爲客戶端鏈接 node3 (目前node3是leader
) 的2888端口。數組
能夠看出來 node3做爲服務節點,由 node4 經過 3888端口創建鏈接進來。
可是 node3 做爲客戶端鏈接node1,node2 的3888端口。
node3 做爲leader
節點,由 node1,node2 ,node4 經過 3888端口創建鏈接進來。
至於爲何 node3能當選 leader 呢?能夠在下面的 選舉過程當中 獲得進一步詳細的闡述。服務器
能夠看出來 node4 做爲客戶端鏈接node1,node2 ,node3 的3888端口。
node4 做爲客戶端鏈接 node3 (目前node3是leader
) 的2888端口。微信
zoo.cfg
的配置後續的server都逐個鏈接前面的server的3888端口,這樣就造成了兩兩鏈接的拓撲,同時也不冗餘。leader
當選時,會開放2888端口,其餘follower
鏈接其2888端口。Zookeeper Atomic Broadcast
)https://zookeeper.apache.org/doc/current/zookeeperInternals.html網絡
ZAB(Zookeeper Atomic Broadcast
)原子廣播是 Paxos
分佈式一致性協議算法(http://zh.wikipedia.org/zh-cn/Paxos) 的一個簡化版本。
首先有如下概念,咱們須要瞭解:
Packet
):經過 FIFO Channel 發送的字節數組。Proposal
):協議的單位。經過與ZooKeeper中的法定server交換數據包來達成協議。大多數提案都包含消息,可是 NEW_LEADER Proposal
提案是不包含消息。Message
):要自動廣播到全部ZooKeeper服務器的字節數組。消息被包含在一個提案(Proposal
)中,而且只有在提案(Proposal
)被經過後消息纔會最終交付delivered
(提交到事務日誌和更新內存的統一視圖)。Quorum
):有 Zookeeper集羣中非observer
角色的全部服務器節點組成,具備投票經過提案(Proposal
)的權力。在 Zookeeper 中提供如下的保證數據的嚴格順序:
delivered
,那麼這個消息最終也被其餘全部的server最終交付delivered
,這裏指最終一致性。delivered
,那麼消息a也是先於b被其餘全部的server最終交付delivered
。如上所述,ZooKeeper保證消息的總順序,也保證建議的總順序。
ZooKeeper使用ZooKeeper transaction id
(zxid) ,這是一個全局的惟一的ID。提出提案(Proposal
)時,全部提案都將附上zxid,進而保證全局的順序性。
leader
將提案(Proposal
)將發送到全部ZooKeeper服務器。
在法定人員(Quorum
)收到後,會確認(acknowledge
)回覆這個提案(Proposal
)給leader
。
其中確認acknowledge
提案(Proposal
)表示服務器已將提案(Proposal
)持久化到日誌中。
稍微注意一下:法定人員(Quorum
)收到提案(Proposal
),只存在確認(acknowledge
),或者由於網絡等緣由超時響應,不存在反對(reject
)。
只要一但知足半數以上(大於全部法定人員的一半)確認acknowledge
後,leader
就會進入正式提交(Commit
)。
若是提案(Proposal
)中包含一條消息,則在提交時將最終交付delivered
該消息。
ZooKeeper消息傳遞包括兩個階段:
Leader activation
):在此階段,leader
被選舉出來,集羣開始變爲對外可用狀態,並準備開始提出提案(Proposal
)。Active messaging
):在此階段,leader
開始接受消息(Message
),併發起提案(Proposal
),協調和決策以提交(Commit
)提案(Proposal
)。leader
產生的條件:
leader
和其鏈接的follower
的個數必須知足半數以上(大於全部法定人員的一半)。當集羣中任意具備選舉權的server發現leader掛了:
NEW_LEADER Proposal
提案,給本身投票,並經過 ZAB 廣播給全部鏈接的 server。NEW_LEADER Proposal
提案的server,若是有被選舉權,則會觸發它的投票行爲:
leader
條件的server,將被選出,同時 follower
也被廣播得到 Proposal
的提交。以上中的 網絡拓撲 爲何 node3能當選 leader 呢?
LOOKING
競選狀態。LOOKING
競選狀態。leader
。消息的傳遞通常指寫請求。
follower
接收到 客戶端的 寫請求後,會轉發給 leader
順序處理。leader
收到寫請求,會檢查數據問題,如無問題,建立一個新的提案proposal
加入toBeApplied
FIFO 隊列,內容是寫請求的消息,並附上全局的ZXid。leader
每次toBeApplied
FIFO 隊列頭部取到一個提案proposal
,經過 ZAB 廣播給全部的 follower
,處於 pending 等待回覆。follower
收到提案proposal
後,記錄提案proposal
持久化到磁盤的日誌文件中,而後確認(acknowledge
)回覆這個提案(Proposal
)給leader
。leader
處於 pending 等待回覆,一旦收到follower
加上本身的確認(acknowledge
)超過半數法定人員(Quorum
),就會觸發 Commit
階段,發送commit
請求給全部的follower
,發送info
請求全部的observer
。leader
將提案proposal
放入 committedRequest 隊列,並從toBeApplied
FIFO 隊列移出該 提案proposal
。follower
收到 Commit
後,會更新本身的內存數據,統一數據視圖。observer
收到info
後,會更新本身的內存數據,統一數據視圖。針對客戶端的讀請求,則不須要轉發給leader
處理。
固然若是是客戶端的sync
命令,則會觸發客戶端鏈接的follower
或observer
向leader
請求同步數據狀態。
@SvenAugustus(https://www.flysium.xyz/)
更多請關注微信公衆號【編程不離宗】,專一於分享服務器開發與編程相關的技術乾貨: