主頁 >  其他 > ZooKeeper-B站黑馬程式員,多多三連

ZooKeeper-B站黑馬程式員,多多三連

2021-10-18 13:51:09 其他

1.zookeeper主要功能

1.1 配置管理

分布式專案的配置總管理處

1.2 分布式鎖

對于分布式專案修改共享資料時加入鎖管理(同一時間只能有一個服務對資料進更改)

1.3 集群管理

最常見的功能,作為注冊中心使用.

2.zookeeper命令操作

2.1 zookeeper資料模型

  • Zookeeper是一個樹形目錄服務,其資料模型和Unix的檔案系統目錄樹很類似,擁有一個層次化結構

  • 這里面的每一個結點都被稱為ZNode,每個節點都會保存自己的資料和節點資訊

  • 節點可以擁有子節點,同時也允許少量(1MB)資料存盤在該節點之下

  • 節點可以分為四大類

    • PERSISTENT 持久化節點

    • EPHEMRAL 臨時節點 : -e

    • PERSISTENT_SENQUENTIAL 持久化順序節點 : -s

    • EPHEMRAL_SEQUENTIAL 臨時順序節點 : -es

2.2 zookeeper 服務端常用命令

在安裝目錄的bin目錄下

  • 啟動Zookeeper服務 : ./zkServer.sh start

  • 查看Zookeeper服務狀態 : ./zkServer.sh statu

  • 停止Zookeeper服務 : ./zkServer.sh stop

  • 重啟Zookeeper服務 : ./zkServer.sh restart

2.3 zookeeper 客戶端常用命令

  • 連接ZooKeeper服務端

    • ./zkCli.sh -server ip:port

  • 斷開客戶端連接

    • quit

  • 設定節點的值

    • set /節點path value

  • 查看幫助命令

    • help

  • 洗掉單個節點

    • delete /節點path

  • 顯示指定目錄下的節點

    • ls 目錄

  • 洗掉帶有子節點的節點

    • deleteall /節點path

  • 創建節點

    • create /節點path value

  • 獲取節點的值

    • get /節點path

  • 創建臨時節點

    • create -e /節點path value

  • 創建順序節點

    • create -s /節點path value

  • 查詢節點詳細資訊

    • ls -s /節點path

  • 節點詳細資訊

    • czxid : 節點被創建的事務ID

    • dataversion : 資料版本號

    • ctime : 創建時間

    • aclversion : 權限版本號

    • mzxid : 最后一次被更新的事務ID

    • ephemeralOwner : 用于臨時節點 ,代表臨時節點的事務ID,如果為持久節點則為0

    • pzxid : 子節點串列最后一次被更新的事務ID

    • dataLength : 節點存盤的資料長度

    • cversion : 子節點的版本號

    • numChildren : 當前節點的子節點數

3.Java API-Cuator

  • Curator是Apache ZooKeeper的Java客戶端庫

4.Java API 常用操作

  • 建立連接

  • 添加節點

  • 洗掉節點

  • 修改節點

  • 查詢節點

  • Watch時間監聽

  • 分布式鎖實作

4.1 建立連接

4.1.1 方式一

        /**
         * Create a new client
         *
         * @param connectString       list of servers to connect to "127.0.0.1:2181'127.0.0.2:8182"
         * @param sessionTimeoutMs    session timeout
         * @param connectionTimeoutMs connection timeout
         * @param retryPolicy         retry policy to use
         * @return client
         */
        //重試策略1 每間隔x一共重試x次  每隔3秒連接一次一共連接10次
        RetryPolicy r = new ExponentialBackoffRetry(3000, 10);
        //第一種方式
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.newClient("116.62.71.234:2181",
                60 * 1000,
                15 * 1000,
                r);
        //開啟連接
        zookeeperClient.start();

4.1.2 方式二 : 鏈式編程

    //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();
  • namespace : 創建根節點itheima(為了方便,不用之后每次進行客戶端操作都寫/根節點path)

4.2 添加節點

4.2.1 基本創建

 public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.235:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * 創建節點
         * 1.基本創建 create().forPath("")
         * 2.創建節點,帶有資料 create.forPath("",data.getBytes())
         * 3.設定節點的型別  create.withMode(CreateMode.ENUM).forPath("")
         * 4.創建多級節點 create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
         */
        /**
         * 基本創建
         * 如果創建節點,沒有指定資料,則默認將當前客戶端的ip作為資料存盤
         */
        String path = zookeeperClient.create().forPath("/app1");
        System.out.println(path);
        //關閉連接
        zookeeperClient.close();
    }

4.2.2 創建節點帶有資料

  • 如果沒有節點資訊,則資訊默認為客戶端ip

public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.235:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();
        //開啟連接
        zookeeperClient.start();
        /**
         * 創建節點
         * 1.基本創建 create().forPath("")
         * 2.創建節點,帶有資料 create.forPath("",data.getBytes())
         * 3.設定節點的型別  create.withMode(CreateMode.ENUM).forPath("")
         * 4.創建多級節點 create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
         */
        /**
         * 基本創建,帶有資料
         * 如果創建節點,沒有指定資料,則默認將當前客戶端的ip作為資料存盤
         */
        String path = zookeeperClient.create().forPath("/app2","hehe".getBytes());
        System.out.println(path);
        //關閉連接
        zookeeperClient.close();
    }

4.2.3 創建節點,設定節點型別

  • 默認為持久化型別

public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.235:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * 創建節點
         * 1.基本創建 create().forPath("")
         * 2.創建節點,帶有資料 create.forPath("",data.getBytes())
         * 3.設定節點的型別  create.withMode(CreateMode.ENUM).forPath("")
         * 4.創建多級節點 create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
         */
        /**
         * 創建節點帶有型別
         * 默認型別:持久化
         */
        String path = zookeeperClient.create().withMode(CreateMode.EPHEMERAL).forPath("/app3","hehe".getBytes());
        System.out.println(path);


        //關閉連接  app3就會被釋放
        zookeeperClient.close();
    }

4.2.4 創建多級節點

  • ZooKeeper如果父節點不存在無法創建子節點

  public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.235:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * 創建節點
         * 1.基本創建 create().forPath("")
         * 2.創建節點,帶有資料 create.forPath("",data.getBytes())
         * 3.設定節點的型別  create.withMode(CreateMode.ENUM).forPath("")
         * 4.創建多級節點 create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
         */
        /**
         * 創建多級節點
         * 父節點不存在無法直接創建子節點
         * creatingParentsIfNeeded
         */
        String path = zookeeperClient.create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
        System.out.println(path);


        //關閉連接  app3就會被釋放
        zookeeperClient.close();
    }

4.3 查詢節點

4.3.1 查詢節點資料

public static void main(String[] args) throws Exception {
            //第二種連接方式:鏈式編程
            CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                    connectString("116.62.71.235:2181").
                    sessionTimeoutMs(60 * 1000).
                    connectionTimeoutMs(15 * 1000).
                    retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                    namespace("itheima").build();

            //開啟連接
            zookeeperClient.start();

            /**
             * 查詢節點
             * 1.查詢資料 get : getData().forPath()
             * 2.查詢子節點 ls getChildren.forPath();
             * 3.查詢節點狀態資訊 ; ls -s getData().storingStatIn(status).forPath("/app1")
             */
            byte[] bytes = zookeeperClient.getData().forPath("/app1");
            System.out.println(new String(bytes));
            //關閉連接
            zookeeperClient.close();
        }

4.3.2 查詢節點子節點

public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.235:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * 查詢節點
         * 1.查詢資料 get : getData().forPath()
         * 2.查詢子節點 ls getChildren.forPath();
         * 3.查詢節點狀態資訊 ; ls -s getData().storingStatIn(status).forPath("/app1")
         */
        List<String> strings = zookeeperClient.getChildren().forPath("/app1");
        //關閉連接
        zookeeperClient.close();
    }

4.3.3 查詢節點詳細資訊 2.3詳見詳細資訊

  • 回傳的結果需要封裝到一個JavaBean中

 public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.235:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * 查詢節點
         * 1.查詢資料 get : getData().forPath()
         * 2.查詢子節點 ls getChildren.forPath();
         * 3.查詢節點狀態資訊 ; ls -s getData().storingStatIn(status).forPath("/app1")
         */
        /**
         * Stat是一個Bean將回傳的節點的詳細資訊封裝到bean中
         */
        Stat status = new Stat();
        zookeeperClient.getData().storingStatIn(status).forPath("/app1");
        //關閉連接
        zookeeperClient.close();
    }

4.4 修改節點資訊

4.4.1 基本修改

  public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.235:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * 修改節點資料
         * 1.修改資料
         * 2.根據版本修改
         */
        zookeeperClient.setData().forPath("/app1","itcast".getBytes());
        //關閉連接
        zookeeperClient.close();
    }

4.4.2 根據版本修改節點資訊(推薦)

 public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * 修改節點資料
         * 1.修改資料
         * 2.根據版本修改
         */
        /**
         * 根據版本修改前需要先查出版本,查詢出的版本和傳入的版本號需要一致才能修改成功,目的就是讓其他客戶端或者其他執行緒不干擾我.
         */
        Stat status = new Stat();
        zookeeperClient.getData().storingStatIn(status).forPath("/app1");
        //查詢出版本
        int version = status.getVersion();
        System.out.println(version);
        zookeeperClient.setData().withVersion(3).forPath("/app1","itcast".getBytes());
        //關閉連接
        zookeeperClient.close();
    }

4.5 洗掉節點

4.5.1 基本洗掉

 public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * 洗掉節點 : delete deleteall
         * 1.洗掉單個節點 delete().forPath();
         * 2.洗掉帶有子節點的節點 delete().deletingChildrenIfNeeded().forPath("/app1");
         * 3.必須成功的洗掉 delete().guaranteed().forPath("/app1"); 為了防止網路抖動,本質就是重試.
         * 4.洗掉回呼  zookeeperClient.delete().guaranteed().inBackground(
         */
        zookeeperClient.delete().forPath("/app1");
        
        //關閉連接
        zookeeperClient.close();
    }

4.5.2 帶有子節點的遞回洗掉

 public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();
        /**
         * 洗掉節點 : delete deleteall
         * 1.洗掉單個節點 delete().forPath();
         * 2.洗掉帶有子節點的節點 delete().deletingChildrenIfNeeded().forPath("/app1");
         * 3.必須成功的洗掉 delete().guaranteed().forPath("/app1"); 為了防止網路抖動,本質就是重試.
         * 4.洗掉回呼  zookeeperClient.delete().guaranteed().inBackground(
         */

        zookeeperClient.delete().deletingChildrenIfNeeded().forPath("/app1");

        //關閉連接
        zookeeperClient.close();
    }

4.5.3 必須洗掉成功

  • guaranteed();

public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();
        /**
         * 洗掉節點 : delete deleteall
         * 1.洗掉單個節點 delete().forPath();
         * 2.洗掉帶有子節點的節點 delete().deletingChildrenIfNeeded().forPath("/app1");
         * 3.必須成功的洗掉 delete().guaranteed().forPath("/app1"); 為了防止網路抖動,本質就是重試.
         * 4.洗掉回呼  zookeeperClient.delete().guaranteed().inBackground(
         */
        zookeeperClient.delete().guaranteed().forPath("/app1");

        //關閉連接
        zookeeperClient.close();
    }

4.5.4 洗掉回呼

  • inBackground(()->{})

public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();
        /**
         * 洗掉節點 : delete deleteall
         * 1.洗掉單個節點 delete().forPath();
         * 2.洗掉帶有子節點的節點 delete().deletingChildrenIfNeeded().forPath("/app1");
         * 3.必須成功的洗掉 delete().guaranteed().forPath("/app1"); 為了防止網路抖動,本質就是重試.
         * 4.洗掉回呼  zookeeperClient.delete().guaranteed().inBackground(
         */
        zookeeperClient.delete().guaranteed().inBackground(new BackgroundCallback(){
            @Override
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("我被洗掉了");
                System.out.println(event);
            }
        }).forPath("/app1");

        //關閉連接
        zookeeperClient.close();
    }

5.Java API 高級操作

5.1 Watch事件監聽

5.1.1 基本概念

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

  • ZooKeeper中引入了Watcher機制來實作了發布/訂閱功能.能夠讓多個訂閱者同時監聽某一個物件,當一個物件自身狀態變化的時候,會通知所有訂閱者.

  • ZooKeeper原生支持通過注冊Watcher來進行事件監聽,但是其使用并不是特別方便需要開發人員自己反復注冊Watcher,比較繁瑣.

  • Curator引入了Cache來實作對ZooKeeper服務端事件的監聽.

  • ZooKeeper提供了三種Watcher;

    • NodeCache : 只是監聽了某一特定節點

    • PathChildrenCache : 監控一個ZNode的子節點

    • TreeCache : 可以監控整個樹上的所有節點,類似于PathChildrenCache和NodeCache組合.

5.1.2 NodeCache

   public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();

        /**
         * NodeCache : 給指定一個節點注冊監聽器
         */
        //1.創建NodeCache物件
        NodeCache nodeCache = new NodeCache(zookeeperClient, "/app1");
        //2.注冊監聽
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                System.out.println("節點變化了");
                //獲取修改節點后的資料
                byte[] data = nodeCache.getCurrentData().getData();
                System.out.println(new String(data));
            }
        });
        //3.開啟監聽,如果設定為true,則開啟監聽時,加載快取資料
        nodeCache.start();;

        //while (true){} //保證執行緒不結束 , web環境不需要加,這里是主方法演示
       
       //關閉連接
        zookeeperClient.close();
    }

5.1.3 PathChildrenCache

  • 引數event可以獲得修改的詳細資訊

 public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();


        /**
         * PathChildrenCache : 監聽某個節點的位元組點
         */
        //1.創建PathChildrenCache物件
        PathChildrenCache p = new PathChildrenCache(zookeeperClient,"/app2",true);
        //2.注冊監聽
        p.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                System.out.println("子節點發送變化了");
                System.out.println(event);
                //監聽子節點的資料變更,并且拿到變更后的資料
                //1.獲取型別
                PathChildrenCacheEvent.Type type = event.getType();
                //2.判斷型別是否為update
                if(type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
                    System.out.println("資料變了");
                    byte[] data = event.getData().getData();
                    System.out.println(new String(data));
                }
            }
        });
        //3.開啟監聽,如果設定為true,則開啟監聽時,加載快取資料
        p.start();

        //while (true){} //保證執行緒不結束 , web環境不需要加,這里是主方法演示
        //關閉連接
        zookeeperClient.close();
    }

5.1.4 TreeCache

public static void main(String[] args) throws Exception {
        //第二種連接方式:鏈式編程
        CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
                connectString("116.62.71.234:2181").
                sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).
                retryPolicy(new ExponentialBackoffRetry(3000, 10)).
                namespace("itheima").build();

        //開啟連接
        zookeeperClient.start();


        /**
         * TreeCache : 監聽某個節點及其子節點
         */
        //1.創建NodeCache物件
        TreeCache treeCache = new TreeCache(zookeeperClient, "/app1");
        //2.注冊監聽
        treeCache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
                System.out.println("結點變化了");
                System.out.println(event);
            }
        });
        //3.開啟監聽,如果設定為true,則開啟監聽時,加載快取資料
        treeCache.start();
        //關閉連接
        zookeeperClient.close();

        //while (true){} //保證執行緒不結束 , web環境不需要加,這里是主方法演示

    }

6.分布式鎖

6.1 分布式鎖

  • 在我們進行單機應用開發,涉及并發同步的時候,我們往往采用synchronized或者lock的方式來解決多執行緒見的代碼同步問題,這時多執行緒的運行都是運行在同一 JVM下,沒有任何問題

  • 但當我們的應用時分布式集群作業的情況下,屬于JVM下的作業環境,跨JVM之間已經無法通過多執行緒的鎖解決同步問題

  • 那么久需要一種更加高級的鎖機制,來處理跨機器的行程之間的資料同步問題---這就是分布式鎖.

6.2 分布式鎖原理

  • 核心思想 : 當客戶端要獲取鎖,則創建節點,使用完鎖則洗掉該節點

    • 客戶端獲取鎖時,在lock節點下創建臨時順序節點

    • 然后分別獲取lock下面的所有子節點,客戶端獲取到所有子節點之后,如果發現自己創建的子節點序號最小,那么就認為該客戶端獲取到了鎖.

    • 如果發現自己創建的節點并非lock所有子節點中最小的,說明還沒有獲取到鎖,此時客戶端需要找到比自己小的那個節點,同時對其注冊事件監聽器,監聽洗掉事件.

    • 如果發現比自己小得那個節點被洗掉,則客戶端的Watcher會受到相應通知,此時再次判斷自己創建的節點是否是lock子節點中序號最小的,如果是則獲取到了鎖,如果不是則重復以上步驟繼續獲取比自己小的一個節點并注冊監聽.

6.3 模擬12306售票案例

  • 在Curator中有五種鎖方案

    • InterProcessSemaphoreMutex : 分布式排它鎖 (非可重入鎖)

    • InterProcessMutex : 分布式可重入排它鎖

    • InterProcessReadWriteLock : 分布式讀寫鎖

    • InterProcessMultiLock : 將多個鎖作為單個物體管理的容器

    • InterProcessSemaphoreV2 : 共享信號量

Runnable

public class Ticket12306 implements Runnable {
    private int tickets = 10;


    //第二種連接方式:鏈式編程
   private static CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
            connectString("116.62.71.235:2181").
            sessionTimeoutMs(60 * 1000).
            connectionTimeoutMs(15 * 1000).
            retryPolicy(new ExponentialBackoffRetry(3000, 10)).
            build();


    private static InterProcessMutex lock = new InterProcessMutex(zookeeperClient,"/lock") ;


    @Override
    public void run() {
        while (true){
            //獲取鎖
            try {
                lock.acquire(3, TimeUnit.SECONDS);
                if(tickets > 0){
                    System.out.println(Thread.currentThread().getName()+":"+tickets);
                    Thread.sleep(100);
                    tickets--;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                //釋放鎖
                try {
                    lock.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


        }
    }
}

Main

public class Lock12306 {
    public static void main(String[] args) {
        Ticket12306 t = new Ticket12306();
        Thread t1 = new Thread(t,"攜程");
        Thread t2 = new Thread(t,"飛豬");
        t1.start();
        t2.start();
    }
}

7 ZooKeeper集群

7.1 集群簡介

  • Leader選舉 :

    • Serverid ; 服務器ID

      • 比如有三臺機器,編號為1,2,3.編號越大在選擇演算法中權重越大.

    • Zxid : 資料ID

      • 服務器中存放的最大資料ID,值越大說明資料越新,在選舉演算法中資料越新則權重越大

    • 在Leader選舉的程序中,如果某臺ZooKeeper獲得了超過半數的選票,則此ZooKeeper就可以成為Leader了

7.2 Zookeer集群搭建

  • 與創建單機環境類似

  • 修改conf目錄下的zoo_sample.cfg為zoo.cfg

  • 修改data目錄為指定目錄,每個集群成員分別配置

  • 在data目錄下創建myid檔案,內容分別為1,2,3

  • 分別在conf目錄下的zoo.cfg檔案加入如下內容

server.1=192.168.149.135:2881:3881
server.2=192.168.149.135:2882:3882
server.3=192.168.149.135:2883:3883
  • 解釋:server.服務器ID=服務器IP地址:服務器之間通信埠:服務器之間投票選舉埠,搭建偽集群,埠可以寫成127.0.0.1

7.3 Zookeeper集群角色

  • Leader領導者

    • 處理事務請求(增刪改)

    • 集群內部各個服務器的調度者

  • Follower跟隨者

    • 處理客戶端非事務請求(查),轉發事務請求給Leader服務器.

    • 引數Leader選舉投票

  • Observer觀察者

    • 處理客戶端非事務請求,轉發事務請求給Leader服務器.

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/321048.html

標籤:其他

上一篇:C/C++程式員編程規范

下一篇:5-2 學習打卡(10.16)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more