那爲何zookeeper能作那麼多事呢,首先咱們來看看它的數據結構。java
zookeeper與redis同樣,都是C/S結構(客戶端和服務端),能夠看作是一個樹,每一個節點稱之爲Znode。node
短暫/臨時(Ephemeral):當客戶端和服務端斷開鏈接後,所建立的Znode(節點)會自動刪除redis
而且zookeeper還須要經過監聽器來監聽Znode節點數據變化以及java子節點的增減變化數據庫
經過監聽+Znode節點(持久/短暫[臨時]),ZooKeeper就能夠玩出這麼多花樣了(統一配置管理、統一命名服務、分佈式鎖、集羣管理...)。數據結構
所謂統一配置管理,就是在分佈式系統中,將多個系統的配置文件的公共配置都提取出來,放入一個新的yml中,而這個yml配置文件放在Znode節點上,分佈式
其餘系統都監聽着Znode這個節點,若是發生變化及時響應。ide
流程圖:spa
流程圖解釋:考慮到全部存儲系統中,數據庫仍是比較成熟可靠的,因此這些配置信息,最終在db中存儲一份。.net
剛開始時,配置管理中心從db中加載公用配置信息,而後同步寫入ZK中,而後各子應用從ZK中讀取配置,並監聽配置的變化(這在ZK中經過Watcher很容易實現)。code
若是配置要修改,一樣也先在配置管理中心中修改,而後持久化到DB,接下來同步更新到ZK,因爲各子應用會監聽數據變化,因此ZK中的配置變化,會實時傳遞到子應用中,子應用固然也無需重啓。
部分代碼以下(這裏的Config是自定義的model類,建立了個znode節點zkConfig),
想要了解ZkClient能夠點擊https://blog.csdn.net/t1dmzks/article/details/78440717
/** * 修改公共配置文件同步到zookeeper */ public void syncConfigToZk(){ //本地zookeeper ZkClient zk = new ZkClient("localhost:2181"); //是否存在zkconfig節點 if(!zk.exists("/zkConfig")){ //建立zookeeper節點 zk.createPersistent("/zkConfig",true); } //更新節點 zk.writeData("/zkConfig", config); zk.close(); } /** * 監聽znode節點變化 */ public Config getConfig() { ZkClient zk = new ZkClient("localhost:2181"); config = (Config)zk.readData("/zkConfig"); System.out.println("加載到配置:"+config.toString()); //監聽zookeeper的zkConfig節點變化 zk.subscribeDataChanges("/zkConfig", new IZkDataListener(){ @Override public void handleDataChange(String arg0, Object arg1) throws Exception { config = (Config) arg1; System.out.println("監聽到配置文件被修改:"+config.toString()); } @Override public void handleDataDeleted(String arg0) throws Exception { config = null; System.out.println("監聽到配置文件被刪除"); } }); return config; }