1. 程式人生 > >zookeeper 在項目中的實際應用

zookeeper 在項目中的實際應用

zookeeper curator

ZooKeeper所提供的服務主要是通過:數據結構Node+原語+watcher機制


ZooKeeper是一個分布式小文件系統,通過選舉算法和集群復制可以避免單點故障,

由於是文件系統,所以即使所有的ZooKeeper節點全部掛掉,數據也不會丟失,

重啟服務器之後,數據即可恢復。


ZooKeeper所實現的一切功能,都是由ZK節點的性質和該節點所關聯的數據實現的,

至於關聯什麽數據那就要看你幹什麽事了

① 集群管理:利用臨時節點特性,節點關聯的是機器的主機名、IP地址等相關信息,集群單點故障也屬於該範疇。

② 統一命名:主要利用節點的唯一性和目錄節點樹結構。

③ 配置管理:節點關聯的是配置信息。

④ 分布式鎖:節點關聯的是要競爭的資源。



以下為項目中的實際應用


1.利用watcher機制

vqsapi 往6個接口發數據的時候,可以用zookeeper來監控目前存活的mongodb與api,

vqsapi 動態獲取,往mongodb與api都存活的接口發數據


2.利用臨時節點的特性

運維接口探測,可以每個服務器在zookeeper註冊一個臨時節點,當接口掛了時候,

session斷開,達到監控的目的


3.利用節點唯一性的特性

分布式鎖,同時操作同一資源,可能出現並發問題時候,上一把鎖

因為原生的zookeeper 語句比較繁瑣,難以理解,所以curator 框架很好的實現了,下面為加鎖操作


String path = String.format(LockPathScheme.STRATEGY_MODEL_ROUTE, modelId, isp,province,value);
       
	   //加鎖操作
       CuratorFramework curator = CuratorFrameworkFactory.builder().retryPolicy(new ExponentialBackoffRetry(10000, 3)).connectString(zookeeperserver).build();
       curator.start();
       InterProcessMutex lock = new InterProcessMutex(curator, path);
       try {
    	   boolean b = lock.acquire(3, TimeUnit.SECONDS);
    	   if (!b) {
    		   resultMap.put("statusCode", 300);
              resultMap.put("message", "記錄正在被操作!");
              return resultMap;
           }
           //加鎖後,該幹嘛幹嘛了
    	    resultMap = this.strategyRoute_dnspod_save_detail(request, id, modelId, modelName, category, province, isp, containCname, type, remark, node, value, ttl, weight, status,customerViewId);
    	   return resultMap;
    	   
       }catch(Exception e){
	    	   e.printStackTrace();
	    	   resultMap.put("statusCode", 300);
	           resultMap.put("message", "內部錯誤!");
	           return resultMap;
       }finally {
       
          //記得一定要釋放鎖
    	   try{
               lock.release();
           }catch (Exception e){
               System.out.println(path + "釋放鎖失敗" + e);
           }
            CloseableUtils.closeQuietly(curator);
       }




最後上一個非常完美的例子,很好的使用了zookeeper 框架的各種特性

轉自 http://www.cnblogs.com/wuxl360/p/5817549.html


假設我們的集群有:


(1) 20個搜索引擎的服務器:每個負責總索引中的一部分的搜索任務。


① 搜索引擎的服務器中的15個服務器現在提供搜索服務。


② 5個服務器正在生成索引。


這20個搜索引擎的服務器,經常要讓正在提供搜索服務的服務器停止提供服務開始生成索引,或生成索引的服務器已經把索引生成完成可以搜索提供服務了。


(2) 一個總服務器:負責向這20個搜索引擎的服務器發出搜索請求並合並結果集。


(3) 一個備用的總服務器:負責當總服務器宕機時替換總服務器。


(4) 一個web的cgi:向總服務器發出搜索請求。


使用Zookeeper可以保證:


(1) 總服務器:自動感知有多少提供搜索引擎的服務器,並向這些服務器發出搜索請求。


(2) 備用的總服務器:宕機時自動啟用備用的總服務器。


(3) web的cgi:能夠自動地獲知總服務器的網絡地址變化。


(4) 實現如下:


① 提供搜索引擎的服務器都在Zookeeper中創建znode,zk.create("/search/nodes/node1", "hostname".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateFlags.EPHEMERAL);


② 總服務器可以從Zookeeper中獲取一個znode的子節點的列表,zk.getChildren("/search/nodes", true);


③ 總服務器遍歷這些子節點,並獲取子節點的數據生成提供搜索引擎的服務器列表;


④ 當總服務器接收到子節點改變的事件信息,重新返回第二步;


⑤ 總服務器在Zookeeper中創建節點,zk.create("/search/master", "hostname".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateFlags.EPHEMERAL);


⑥ 備用的總服務器監控Zookeeper中的"/search/master"節點。當這個znode的節點數據改變時,把自己啟動變成總服務器,並把自己的網絡地址數據放進這個節點。


⑦ web的cgi從Zookeeper中"/search/master"節點獲取總服務器的網絡地址數據,並向其發送搜索請求。


⑧ web的cgi監控Zookeeper中的"/search/master"節點,當這個znode的節點數據改變時,從這個節點獲取總服務器的網絡地址數據,並改變當前的總服務器的網絡地址。


本文出自 “布拉君君” 博客,請務必保留此出處http://5148737.blog.51cto.com/5138737/1972492

zookeeper 在項目中的實際應用