之前寫過一篇文章,講了下如何基於Zookeeper和Curator框架寫Master選舉的Demo,本文來細說下Curator框架在進行Master選舉的時候,內部是如何實現的。
Demo可以查看之前寫的那篇文章《一個簡單的基於Zookeeper實現主從選舉的例子》。
客戶端調用LeaderClient.start()方法開始進行Master選舉,start()方法內部會執行internalStart()方法:
reset()方法就是Master選舉的核心,方法內部分成了兩個步驟:
1.在Master選舉的ZK路徑下創建EPHEMERAL_SEQUENTIAL(臨時有序節點)
client.create().creatingParentsIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).inBackground(callback).forPath(ZKPaths.makePath(latchPath, LOCK_NAME), LeaderSelector.getIdBytes(id));
臨時有序節點命名格式爲PROTECTED_PREFIX+UUID+LOCK_NAME+編號,例如有兩個節點進行Master選舉,它們的名字分別如下:
_c_8c79d7bc-9ef2-43f8-a0d2-b136f51a9a16-latch-0000000049
_c_b4e6bdef-052e-448c-aaaf-de157c982f01-latch-0000000048
2.節點創建完畢之後,回調執行callback方法,內部會執行getChildren():
該方法內部調用checkLeadership()方法:
checkLeadership()方法會對Master選舉路徑下的節點進行排序,對於index爲0的標記爲leader(即編號最小的會被當成leader);對於index大於0的則添加watch,watch的路徑爲前一個節點;如果前一個節點被刪除了(Event.EventType.NodeDeleted),則重新觸發getChildren()方法。
這個方法隨後還註冊一個callback,如果前一個節點被刪除,則重新觸發reset()操作:
不太明白這裏是爲啥了...因爲前面不是已經註冊過watch了麼…望知道的大神幫忙解釋一下
LeaderLatch內部還使用了ConnectionStateListener對自身節點變化進行相應處理:
handleStateChange(newState)中對不同的Session狀態進行的處理如下:
可以看出,各種情況考慮的確實很到位啊!!!
個人也得出瞭如下結論:
如果在運行的時候Master進程如果被kill掉了,那麼就一定會發生主備切換。因爲原Master進程啓動之後,這個新的進程在Master選舉的ZK路徑下創建的肯定是一個新的節點。
拿上篇文章中寫的那個Demo程序驗證了下,發現確實是這樣的。