ZooKeeper 是一個分佈式的,開放源碼的分佈式應用程序協同服務。
ZooKeeper 的設計目標是將那些複雜且容易出錯的分佈式一致性服 務封裝起來,構成一個高效可靠的原語集,並以一系列簡單易用 的接口提供給用戶使用。node
一、發佈者將數據發佈到Zookeeper的節點上,供訂閱者進行數據訂閱。
二、Zookeeper採用了推拉相結合的模式,客戶端向服務端註冊本身須要關注的節點,一旦該節點數據發生變動,那麼服務端就會向相應的客戶端推送Watcher事件通知,客戶端接收到此通知後,主動到服務端獲取最新的數據。算法
一、排它鎖也叫獨佔鎖服務器
① 獲取鎖,在須要獲取排它鎖時,全部客戶端經過調用接口,在/exclusive_lock節點下建立臨時子節點/exclusive_lock/lock。Zookeeper能夠保證只有一個客戶端可以建立成功,沒有成功的客戶端須要註冊/exclusive_lock節點監聽。分佈式
② 釋放鎖,當獲取鎖的客戶端宕機或者正常完成業務邏輯都會致使臨時節點的刪除,此時,全部在/exclusive_lock節點上註冊監聽的客戶端都會收到通知,能夠從新發起分佈式鎖獲取。ide
二、讀寫鎖設計
① 獲取鎖,在須要獲取共享鎖時,全部客戶端都會到/shared_lock下面建立一個臨時順序節點,若是是讀請求,那麼就建立例如/shared_lock/host1-R-00000001的節點,若是是寫請求,那麼就建立例如/shared_lock/host2-W-00000002的節點。日誌
② 判斷讀寫順序server
1. 建立完節點後,獲取/shared_lock節點下全部子節點,並對該節點變動註冊監聽。blog
2. 肯定本身的節點序號在全部子節點中的順序。接口
3. 對於讀請求:若沒有比本身序號小的子節點或全部比本身序號小的子節點都是讀請求,那麼代表本身已經成功獲取到共享鎖,同時開始執行讀取邏輯,如有寫請求,則須要等待。對於寫請求:若本身不是序號最小的子節點,那麼須要等待。
4. 接收到Watcher通知後,重複步驟1。
③ 釋放鎖,其釋放鎖的流程與獨佔鎖一致。
兩種鎖如何避免羊羣效應?
一、獨佔鎖:
二、讀寫鎖呢?
一、master-worker模式
一個Kafka集羣由多個broker組成,這些borker是系統中的worker。Kafka會從這些worker選舉出一個 controller,這個controlle是系統中的master,負責把topic和partition分配給各個broker。
二、Topic註冊
Topic的消息會被分紅多個分區並將其分佈在多個Broker上,這些分區信息及與Broker的對應關係也都是由Zookeeper在維護。
三、消費分區與消費者的關係,消息消費位移記錄
同一個消費者組內,每一個分區只能有一個消費者進行消費,每條消息只被消費一次,因此消費者和消費分區之間的關係也寫入zookeeper。
ZooKeeper 使用文件系統模型,Datatree。Datatree 的每一個節點叫做 znode。每一個節點均可以保存數據。每一個節點都有一個版本 (version)。版本從 0 開始計數。
基於版本號的條件更新
quorum模式要求至少3個節點
其中2181是默認客戶端服務端口,3333是quorum之間的通訊,3334是用於leader選舉的端口。
• 可線性化(Linearizable)寫入:先到達 leader 的寫請求會被先處理,leader 決定寫請求的執 行順序。
• 客戶端FIFO順序:來自給定客戶端的請求按照發送順序執行。
一、2PC,3PC,Paxos,Raft算法
二、ZAB(ZooKeeper Atomic Broadcast)協議
一、Vote投票包含的信息:sid(服務器ID),zxid(事務ID),epoch(leader週期)
二、投票過程
一個ZooKeeper節點經過向全部的節點發送vote開始選舉
一個節點在接收到vote以後若是發現接收到的投票新,就把本身的投票更新成最新的投票,並把vote發送給全部的ZooKeeper節點。不然的話,什麼也不用作。
如何判斷一個投票是新的?
一個3節點集羣選舉一個leader的時序圖:
三、腦裂-長時間的消息發送延遲致使選舉出兩個leader