原理就是利用ZK同級節點的惟一性.服務器
Curator框架下的一些分佈式鎖工具
InterProcessMutex:分佈式可重入排它鎖 網絡
InterProcessSemaphoreMutex:分佈式排它鎖 session
InterProcessReadWriteLock:分佈式讀寫鎖框架
使用 Zookeeper 實現 leader 選舉分佈式
Leader Latch ide
參與選舉的全部節點,會建立一個順序節點,其中最小的 節點會設置爲 master 節點, 沒搶到 Leader 的節點都監聽前一個節點的刪除事件,在前一個節點刪除後進行從新搶主,當 master 節點手動調用 close()方法或者 master 節點掛了以後,後續的子節點會搶佔 master。 其中 spark 使用的就是這種方法 工具
LeaderSelector ui
LeaderSelector 和 Leader Latch 最的差異在於,leader 能夠釋放領導權之後,還能夠繼續參與競爭this
public class LeaderSelectorClient extends LeaderSelectorListenerAdapter implements Closeable { private String name; //表示當前的進程 private LeaderSelector leaderSelector; //leader選舉的API private CountDownLatch countDownLatch=new CountDownLatch(1); public LeaderSelectorClient(){ } public LeaderSelectorClient(String name) { this.name = name; } public LeaderSelector getLeaderSelector() { return leaderSelector; } public void setLeaderSelector(LeaderSelector leaderSelector) { this.leaderSelector = leaderSelector; } public void start(){ leaderSelector.start(); //開始競爭leader } @Override public void takeLeadership(CuratorFramework client) throws Exception { //若是進入當前的方法,意味着當前的進程得到了鎖。得到鎖之後,這個方法會被回調 //這個方法執行結束以後,表示釋放leader權限 System.out.println(name+"->如今是leader了"); // countDownLatch.await(); //阻塞當前的進程防止leader丟失 } @Override public void close() throws IOException { leaderSelector.close(); } private static String CONNECTION_STR="x.x.x.x:2181; public static void main(String[] args) throws IOException { CuratorFramework curatorFramework = CuratorFrameworkFactory.builder(). connectString(CONNECTION_STR).sessionTimeoutMs(50000000). retryPolicy(new ExponentialBackoffRetry(1000, 3)).build(); curatorFramework.start(); LeaderSelectorClient leaderSelectorClient=new LeaderSelectorClient("ClientA"); LeaderSelector leaderSelector=new LeaderSelector(curatorFramework,"/leader",leaderSelectorClient); leaderSelectorClient.setLeaderSelector(leaderSelector); leaderSelectorClient.start(); //開始選舉 System.in.read(); } }
ZAB 協議包含兩種基本模式,spa
1. 崩潰恢復[master節點選擇]
2. 原子廣播[數據恢復,數據同步]
當整個集羣在啓動時,或者當 leader 節點出現網絡中斷、 崩潰等狀況時,ZAB 協議就會進入恢復模式並選舉產生新 的 Leader,當 leader 服務器選舉出來後,而且集羣中有過 半的機器和該 leader 節點完成數據同步後(同步指的是數 據同步,用來保證集羣中過半的機器可以和 leader 服務器 的數據狀態保持一致),ZAB 協議就會退出恢復模式。
當集羣中已經有過半的 Follower 節點完成了和 Leader 狀 態同步之後,那麼整個集羣就進入了消息廣播模式。這個時候,在 Leader 節點正常工做時,啓動一臺新的服務器加入到集羣,那這個服務器會直接進入數據恢復模式,和 leader 節點進行數據同步。同步完成後便可正常對外提供非事務請求的處理。
須要注意的是:leader 節點能夠處理事務請求和非事務請 求,follower 節點只能處理非事務請求,若是 follower 節 點接收到非事務請求,會把這個請求轉發給 Leader 服務器
ZK數據同步流程過程其實是一個 簡化版本的二階段(2pc)提交過程
1. leader 接收到消息請求後,將消息賦予一個全局惟一的 64 位自增 id,叫:zxid,經過 zxid 的大小比較既能夠實現因果有序這個特徵 2. leader 爲每一個 follower 準備了一個 FIFO 隊列(經過 TCP 協議來實現,以實現了全局有序這一個特色)將帶有 zxid 的消息做爲一個提案(proposal)分發給全部的 follower 3. 當 follower 接收到 proposal,先把 proposal 寫到磁盤, 寫入成功之後再向 leader 回覆一個 ack 4. 當 leader 接收到合法數量(超過半數節點)的 ACK 後,leader 就會向這些 follower 發送 commit 命令,同時會 在本地執行該消息 5. 當 follower 收到消息的 commit 命令之後,會提交該消息
爲了保證事務的順序一致性,zookeeper 採用了遞增的事 務 id 號(zxid)來標識事務。
全部的提議(proposal)都 在被提出的時候加上了 zxid。實現中 zxid 是一個 64 位的 數字,它高 32 位是 epoch(ZAB 協議經過 epoch 編號來 區分 Leader 週期變化的策略)用來標識 leader 關係是否改變,每次一個 leader 被選出來,它都會有一個新的 epoch=(原來的 epoch+1),標識當前屬於那個 leader 的 統治時期。低 32 位用於遞增計數。
epoch:能夠理解爲當前集羣所處的年代或者週期,每一個leader 就像皇帝,都有本身的年號,因此每次改朝換代,leader 變動以後,都會在前一個年代的基礎上加1。這樣就算舊的 leader 崩潰恢復以後,也沒有人聽他的了,由於 follower 只遵從當前年代的 leader 的命令。