中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

zookeeper入門到實戰

發布時間:2020-08-03 01:34:58 來源:網絡 閱讀:887 作者:Java_老男孩 欄目:編程語言

一.zookeeper介紹

ZooKeeper 是一個開源的分布式協調服務,由雅虎創建,是 Google Chubby 的開源實現。分布式應用程序可以基于 ZooKeeper 實現諸如數據發布/訂閱負載均衡命名服務分布式協調/通知集群管理Master 選舉配置維護名字服務分布式同步分布式鎖和分布式隊列等功能。

數據模型ZooKeeper 允許分布式進程通過共享的層次結構命名空間進行相互協調,這與標準文件系統類似。名稱空間由 ZooKeeper 中的數據寄存器組成,稱為 Znode,這些類似于文件和目錄。與典型文件系統不同,ZooKeeper 數據保存在內存中,這意味著 ZooKeeper 可以實現高吞吐量和低延遲

順序訪問:對于來自客戶端的每個更新請求,ZooKeeper 都會分配一個全局唯一的遞增編號。這個編號反應了所有事務操作的先后順序,應用程序可以使用 ZooKeeper 這個特性來實現更高層次的同步原語。這個編號也叫做時間戳zxidZooKeeper Transaction Id)。

可構建集群:為了保證高可用,最好是以集群形態來部署 ZooKeeper,這樣只要集群中大部分機器是可用的(能夠容忍一定的機器故障),那么 ZooKeeper 本身仍然是可用的。客戶端在使用 ZooKeeper 時,需要知道集群機器列表,通過與集群中的某一臺機器建立 TCP 連接來使用服務。客戶端使用這個 TCP 鏈接來發送請求、獲取結果、獲取監聽事件以及發送心跳包。如果這個連接異常斷開了,客戶端可以連接到另外的機器上。

zookeeper入門到實戰

  • 上圖中每一個 Server 代表一個安裝 ZooKeeper 服務的服務器。組成 ZooKeeper服務的服務器都會在內存中維護當前的服務器狀態,并且每臺服務器之間都互相保持著通信。集群間通過 Zab 協議(Zookeeper Atomic Broadcast)來保持數據的一致性。
  • Zookeeper服務器有三種角色:LeaderFollowerObserver,集群中的所有機器通過一個 Leader 選舉過程來選定一臺稱為 “Leader” 的機器。Leader 既可以為客戶端提供寫服務又能提供讀服務。除了 Leader 外,FollowerObserver只能提供讀服務FollowerObserver 唯一的區別在于Observer 機器不參與 Leader 的選舉過程,也不參與寫操作的“過半寫成功”策略,因此 Observer 機器可以在不影響寫性能的情況下提升集群的讀性能。
  • ZooKeeper 中,主要依賴 ZAB 協議來實現分布式數據一致性,基于該協議,ZooKeeper實現了一種主備模式的系統架構來保持集群中各個副本之間的數據一致性

工作原理

  1. Zookeeper的核心是原子廣播,這個機制保證了各個server之間的同步。實現這個機制的協議叫做Zab協議
  2. Zab協議有兩種模式,它們分別是恢復模式廣播模式。當服務啟動或者在領導者崩潰后,Zab就進入了恢復模式,當領導者被選舉出來,且大多數server的完成了和leader狀態同步以后,恢復模式就結束了。狀態同步保證了leaderserver具有相同的系統狀態。一旦leader已經和多數的follower進行了狀態同步后,他就可以開始廣播消息了,即進入廣播狀態。這時候當一個server加入zookeeper服務中,它會在恢復模式下啟動,發現leader,并和leader進行狀態同步。待到同步結束,它也參與消息廣播。
  3. Zookeeper服務一直維持在Broadcast狀態,直到leader崩潰了或者leader失去了大部分的followers支持

Leader選舉

  1. 廣播模式需要保證proposal提議)被按順序處理leader來執行寫操作),因此zk采用了遞增的事務id號(zxid)來保證。所有的提議都在被提出的時候加上了zxid。實現中zxid是一個64為的數字,它高32位是epoch用來標識leader關系是否改變,每次一個leader被選出來,它都會有一個新的epoch。低32位是個遞增計數。
  2. leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的server恢復到一個正確的狀態。每個Server啟動以后都詢問其它的Server它要投票給誰。對于其他server的詢問,server每次根據自己的狀態都回復自己推薦的leaderid和上一次處理事務的zxid(系統啟動時每個server都會推薦自己),收到所有Server回復以后,就計算出zxid最大的哪個Server,并將這個Server相關信息設置成下一次要投票的Server。計算這過程中獲得票數最多的的sever為獲勝者,如果獲勝者的票數超過半數,則改server被選為leader。否則,繼續這個過程,直到leader被選舉出來

二.使用Zookeeper

 1        //客戶端連接zookeeper服務器
 2         ZooKeeper zkClient = new ZooKeeper(CONNECT_STR, 50000, new Watcher() {
 3             @Override
 4             public void process(WatchedEvent watchedEvent) {
 5                 //監控服務節點變化
 6                 System.out.println("sssss");
 7             }
 8         });
 9         
10         //獲取根節點下的所有節點
11         List<String> nodeList= zkClient.getChildren("/",null);
12 
13         System.out.println(nodeList.toString());
14 
15         //Stat isExists= zkClient.exists(LOCK_ROOT_PATH,null);
16         //在test父節點下創建子節點
17         String lockPath = zkClient.create("/test/why","why".getBytes(),            
18         ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);

代碼中需要注意的是如果父節點不存在,會報異常,同時父節點不能是臨時節點。

Znode

  1. ZooKeeper中,“節點"分為兩類,第一類同樣是指構成集群的機器,我們稱之為機器節點,第二類則是指數據模型中的數據單元,我們稱之為數據節點一ZNode。
  2. ZooKeeper 將所有數據存儲在內存中,數據模型是一棵樹(Znode Tree),由斜杠(/)的進行分割的路徑,就是一個
    Znode,例如/foo/path2。每個上都會保存自己的數據內容,同時還會保存一系列屬性信息。
  3. zookeeper有四類節點:PERSISTENT(持久的)EPHEMERAL(暫時的)PERSISTENT_SEQUENTIAL(持久化順序編號目錄節點)EPHEMERAL_SEQUENTIAL(暫時化順序編號目錄節點)

Session

  1. Session 指的是 ZooKeeper 服務器與客戶端會話。在 ZooKeeper 中,一個客戶端連接是指客戶端和服務器之間的一個 TCP 長連接
  2. 客戶端啟動的時候,首先會與服務器建立一個 TCP連接,從第一次連接建立開始客戶端會話的生命周期也開始了。通過這個連接,客戶端能夠通過心跳檢測與服務器保持有效的會話,也能夠向Zookeeper 服務器發送請求并接受響應,同時還能夠通過該連接接收來自服務器的 Watch 事件通知
  3. SessionsessionTimeout值用來設置一個客戶端會話的超時時間。當由于服務器壓力太大、網絡故障或是客戶端主動斷開連接等各種原因導致客戶端連接斷開時,只要在sessionTimeout規定的時間內能夠重新連接上集群中任意一臺服務器,那么之前創建的會話仍然有效。在為客戶端創建會話之前,服務端首先會為每個客戶端都分配一個sessionID。由于 sessionIDZookeeper 會話的一個重要標識,許多與會話相關的運行機制都是基于這個sessionID 的。因此,無論是哪臺服務器為客戶端分配的 sessionID,都務必保證全局唯一

Watcher:是 ZooKeeper 中的一個很重要的特性。ZooKeeper 允許用戶在指定節點上注冊一些 Watcher,并且在一些特定事件觸發的時候,ZooKeeper 服務端會將事件通知到感興趣的客戶端上去,該機制是 ZooKeeper 實現分布式協調服務的重要特性。

Version: Zookeeper 的每個 ZNode 上都會存儲數據,對應于每個 ZNodeZookeeper 都會為其維護一個叫作 Stat 的數據結構。Stat 中記錄了這個 ZNode 的三個數據版本,分別是:version(當前節點版本)、cversion當前節點的子節點版本)、aversion當前節點的ACL版本

ACLZooKeeper 采用 ACLAccessControlLists)策略來進行權限控制,類似于 UNIX 文件系統的權限控制。ZooKeeper 定義了 5 種權限:CREATE/READ/WRITE/DELETE/ADMIN


三.通過zookeeper實現分布式鎖

      package com.why;

      import org.apache.zookeeper.*;
      import org.apache.zookeeper.data.Stat;

      import java.io.IOException;
      import java.util.Collections;
      import java.util.List;

     /*
     *  分布式鎖
     * */
     public class DistributeLock {

         private static final String LOCK_ROOT_PATH = "/test";
         //private static final String LOCK_NODE_NAME = "Lock";

         private static ZooKeeper _zkClient;

         static {
             try {
                 _zkClient = new ZooKeeper("192.168.6.132:2181", 500000, null);
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }

         public static String getLock() {
             try {

                 //System.out.println(_zkClient.getChildren("/",false));

                 String lockPath = _zkClient.create( "/test/why", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
                 //System.out.println(lockPath);
                 //System.out.println(_zkClient.getChildren(LOCK_ROOT_PATH,false));
                 if (tryLock(lockPath))
                     return lockPath;
                 else
                     return null;
             } catch (Exception ex) {
                 ex.printStackTrace();
                 return null;
             }
         }

         private static boolean tryLock(String lockPath) throws KeeperException, InterruptedException {
             List<String> lockPaths = _zkClient.getChildren(LOCK_ROOT_PATH, false);
             Collections.sort(lockPaths);
             int index=lockPaths.indexOf(lockPath.substring(LOCK_ROOT_PATH.length()+1));
             if(index==0){
                 //獲得鎖
                 return true;
             }
             else{
                 String preLockPath="/"+lockPaths.get(index-1);

                 Watcher watcher=new Watcher() {
                     @Override
                     public void process(WatchedEvent watchedEvent) {
                         synchronized (this){
                             //喚醒線程
                             notifyAll();
                         }
                     }
                 };

                 Stat stat=_zkClient.exists(preLockPath,watcher);

                 if(stat==null){
                     return tryLock(lockPath);
                 }else{
                     synchronized (watcher){
                         watcher.wait();
                     }
                     return tryLock(lockPath);
                 }

             }

         }

         public static void closeZkClient() throws InterruptedException {
             _zkClient.close();
         }

         public static void releaseLock(String lockPath) throws KeeperException, InterruptedException {
             _zkClient.delete(lockPath,-1);
         }
     }

測試:

    package com.why;

    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.ZooKeeper;

    import java.io.IOException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;

    public class MultiThreadDemo {

        private static  int counter = 0;

        public  static  void plus() throws InterruptedException {
            Thread.sleep(500);
            counter++;
            //System.out.println(counter);
        }

        public static int Count(){
            return counter;
        }

        public static void main(String[] args) throws IOException, KeeperException, InterruptedException {

            ExecutorService executor= Executors.newCachedThreadPool();
            final int num=10;
            for(int i=0;i<num;i++){
                executor.submit(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String path = DistributeLock.getLock();
                            System.out.println(path);
                            plus();
                            DistributeLock.releaseLock(path);
                            System.out.println(Count());
                        } catch (InterruptedException | KeeperException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            executor.shutdown();

        }
    }

文末彩蛋

針對于上面所涉及到的知識點我總結出了有1到5年開發經驗的程序員在面試中涉及到的絕大部分架構面試題及答案做成了文檔和架構視頻資料免費分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并發等架構技術資料),希望能幫助到您面試前的復習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習,也可以關注我一下以后會有更多干貨分享。

資料獲取方式 QQ群搜索“708-701-457” 即可免費領取

zookeeper入門到實戰
zookeeper入門到實戰
zookeeper入門到實戰

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

渝北区| 策勒县| 乐山市| 南宫市| 同仁县| 酒泉市| 福泉市| 班戈县| 睢宁县| 岳普湖县| 城步| 施秉县| 喀喇| 七台河市| 屏山县| 永平县| 贵德县| 林西县| 齐齐哈尔市| 菏泽市| 嘉定区| 保德县| 河北省| 综艺| 同仁县| 色达县| 乐陵市| 建宁县| 鄂伦春自治旗| 隆昌县| 洪洞县| 西青区| 阳朔县| 沈阳市| 深圳市| 和田县| 济南市| 伊宁市| 定远县| 镇坪县| 曲阳县|