大數據學習(十五)zookeeperAPI操作 zookeeper分佈式鎖

zookeeperAPI

package zkApI;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

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

/**
 * @Author: Braylon
 * @Date: 2020/1/30 10:47
 * @Version: 1.0
 */
public class zookeeper {
    //對集羣的配置,這裏使用僞分佈
    private static String destination = "ip:2181";
    private static int sessionTimeout = 2000;
    private ZooKeeper zkClient = null;

    @Before
    public void init() throws IOException {
        zkClient = new ZooKeeper(destination, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                //收到事件通知後執行的函數,也就似乎用戶的業務邏輯
                System.out.println("監聽" + "\001" + watchedEvent.getPath());

                //重新開始監聽
                try {
                    zkClient.getChildren("/", true);
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Test
    public void crearePoint() {
        /*對於create方法
        * P1:創建的節點路徑
        * P2:數據
        * P3:節點的權限
        * P4:節點的類型
        * */
        try {
            zkClient.create("/braylon", "point01".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void getChild() {
        try {
            List<String> children = zkClient.getChildren("/", true);
            for (String c : children) {
                System.out.println(c);
            }
            //延時阻塞
            Thread.sleep(Long.MAX_VALUE);

        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void isExited() {
        try {
            Stat s = zkClient.exists("/braylon", false);
            System.out.println(s == null ? "不存在" : "存在");
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

這裏其實沒有什麼特別好說的,因爲基本上都是很簡單的操作,不過可以可以關注一下,@Before這個並不是zookeeper開發包中的,而是junit中的,答題的邏輯就是在運行Test之前先運行@Before註解下的監聽器。

大家運行一些就明白了。

分佈式鎖

分佈式鎖一共有三種無非是利用原子性操作來達到。

  1. 數據庫
  2. redis
  3. zookeeper鎖

都可以實現分佈式鎖,

我知道的是redis用的好像比較多,當然我在上本科,所以也許是沒有接觸過特別高逼格的分佈式鎖。但是我一直覺得zookeeper鎖使用比redis更加簡單,主要應該是本身zookeeper的機制和開發包的封裝性已經非常“傻瓜了”。

這裏我分享一個小demo:

我使用的就是一個本地部署zookeeper的虛擬機,哈哈很簡單吧。

package zkApI;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

/**
 * @Author: Braylon
 * @Date: 2020/1/30 11:23
 * @Version: 1.0
 */
public class zkDistributionLock {
    private static Integer sharedResource = 5;

    public static void print() {
        System.out.println("**************" + Thread.currentThread().getName() + "**************");
        System.out.println("Get sharedResource");
        if (sharedResource == 0) {
            System.out.println("sorry, your operation fails");
            return;
        }
        sharedResource = sharedResource - 1;
        System.out.println("left " + sharedResource);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("************************done\n");
    }

    public static void main(String[] args) {
        //等待時間和最大重試次數
        ExponentialBackoffRetry policy = new ExponentialBackoffRetry(1000, 10);

        CuratorFramework client = CuratorFrameworkFactory.builder().connectString("ip:2181").retryPolicy(policy).build();
        //生成鎖
        client.start();
        final InterProcessMutex mutex = new InterProcessMutex(client, "/lock0130");
        //多線程併發訪問
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //在訪問共享資源之前獲得鎖
                        mutex.acquire();
                        print();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }finally {
                        //釋放鎖
                        try {
                            mutex.release();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    }
}

歡迎大神指點
祝福武漢
大家共勉~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章