zookeeper学习

https://blog.csdn.net/u012152619/article/category/6470028

目前zookeeper常用的开发包有zkclient跟curator,后者更为方便,日常开发使用较多。

 

1. 分布式锁:

public class Test {
    private static final String    HOST = "localhost:2181";

    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
        ZkClient zkClient = new ZkClient(HOST, 5000, 5000, new SerializableSerializer());
        Resources resources = new Resources();
        Runnable finishTask = new FinishTask(resources);
        CyclicBarrier barrier = new CyclicBarrier(10, finishTask);
        
        for(int i = 0; i < 10; i++){
            Task t = new Task(zkClient, resources, barrier, "test" + i);
            t.start();
        }
    }
}

 

 

public class Resources {
    private int count;

    public int plus(){
        try {
            Thread.sleep(1000l);
            count++;
            System.out.println(Thread.currentThread().getName() + " 当前count值为 : " + count);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return count;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

 

public class FinishTask implements Runnable{
    private Resources resources;
    
    public FinishTask(Resources resources){
        this.resources = resources;
    }
    
    @Override
    public void run() {
        System.out.println("操作完成 ! count : " + resources.getCount());
    }

}

 

public class Task extends Thread{
    private static final String    LOCK_ROOT_PATH = "/lock";
    
    private Resources resources;
    private CyclicBarrier barrier;
    private ZkClient zkClient;
    
    
    public Task(ZkClient zkClient, Resources resources, CyclicBarrier barrier, String name) {
        this.zkClient = zkClient;
        this.resources = resources;
        this.barrier = barrier;
        super.setName(name);
        
    }

    @Override
    public void run() {
        String path = this.getLock();
        resources.plus();
        releaseLock(path);
        try {
            barrier.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
    
    private void releaseLock(String path) {
        zkClient.delete(path, -1);
    }

    
    private String getLock() {
        String path = RegisterNode();
        try {
            tryLock(path);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return path;
    }
    
    private boolean tryLock(String path) throws InterruptedException {
        List<String> lockPaths = zkClient.getChildren(LOCK_ROOT_PATH);
        Collections.sort(lockPaths);
 
        int index = lockPaths.indexOf(path.substring(LOCK_ROOT_PATH.length() + 1));
        if (index == 0) {
            System.out.println(this.getName() + " get lock, lockPath: " + path);
            return true;
        } else {
            String preLockPath = lockPaths.get(index - 1);
            
            IZkDataListener listener = new IZkDataListener() {
                @Override
                public void handleDataDeleted(String watcherPath) throws Exception {
                    System.out.println(watcherPath + " has been deleted");
                    synchronized(this){
                        this.notifyAll();
                    }
                }
                
                @Override
                public void handleDataChange(String path, Object data) {
                }
            };
            
            boolean exist = zkClient.exists(LOCK_ROOT_PATH + "/" + preLockPath);
     
            if (!exist) {
                return tryLock(path);
            } else {
                zkClient.subscribeDataChanges(LOCK_ROOT_PATH + "/" + preLockPath, listener);
                System.out.println(Thread.currentThread().getName() + " wait for " + preLockPath);
                synchronized(listener){
                    listener.wait();
                }
                return tryLock(path);
            }
        }

    }
    
    private String RegisterNode(){
        String path = zkClient.create(LOCK_ROOT_PATH + "/lock_", super.getName(), CreateMode.EPHEMERAL_SEQUENTIAL);
        return path;
    }

 

2. 队列

public class Test {
    
    public static void main(String[] args) {
        final ZkBlockingQueue queue = new ZkBlockingQueue(8, "queue");
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 1; i <= 1000; i++){
                    queue.put(""+i);
                }
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 1; i <= 1000; i++){
                    queue.take();
                }
            }
        }).start();
    }
}

 

public class ZkBlockingQueue {
    
    private static final String    HOST = "localhost:2181";
    private static final String    QUEUE_ROOT_PATH = "/queue";

    private final int MAX_STORE_SIZE;
    
    private Producer producer;
    private Customer customer;
    
    public ZkBlockingQueue(int max, String name){
        MAX_STORE_SIZE = max;
        producer = new Producer(this);
        customer = new Customer(this);
    }
    
    public void put(String s){
        producer.put(s);
    }
    
    public String take(){
        return customer.take();
    }
    
    public class Producer{
        
        private ZkClient zkClient;
        private ZkBlockingQueue queue;
        
        public Producer(ZkBlockingQueue zkBlockingQueue){
            this.zkClient = new ZkClient(HOST, 5000, 5000, new SerializableSerializer());
            queue = zkBlockingQueue;
            
        }
        
        private void put(final String s) {
            while(true){
                int size = zkClient.countChildren(QUEUE_ROOT_PATH);
                
                if(size != queue.MAX_STORE_SIZE){
                    String path = RegisterNode(s);
                    System.out.println( "create path : " + path + " value : " + s);
                    break;
                    
                }else{
                    System.out.println("queue is full !");
                    IZkChildListener listener = new IZkChildListener() {
                        
                        @Override
                        public void handleChildChange(String parentPath, List<String> currentChilds)
                                throws Exception {
                            if(currentChilds.size() < queue.MAX_STORE_SIZE){
                                synchronized (this) {
                                    this.notify();
                                }
                            }
                        }
                    };
                    
                    zkClient.subscribeChildChanges(QUEUE_ROOT_PATH, listener);
                    synchronized (listener) {
                        try {
                            listener.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

        private String RegisterNode(String s){
            String path = zkClient.create(QUEUE_ROOT_PATH + "/number_", s, CreateMode.EPHEMERAL_SEQUENTIAL);
            return path;
        }
    }
    
    public class Customer{
        
        private ZkClient zkClient;
        
        public Customer(ZkBlockingQueue zkBlockingQueue){
            this.zkClient = new ZkClient(HOST, 5000, 5000, new SerializableSerializer());
        }
        
        private String take() {
            while(true){
                int size = zkClient.countChildren(QUEUE_ROOT_PATH);
                
                if(size != 0){
                    List<String> lockPaths = zkClient.getChildren(QUEUE_ROOT_PATH);
                    Collections.sort(lockPaths);
                    String value = takeNode("/" + lockPaths.get(0));
                    System.out.println("get data : " + value);
                    return value;
                }else{
                    System.out.println("queue is empty !");
                    IZkChildListener listener = new IZkChildListener() {
                        
                        @Override
                        public void handleChildChange(String parentPath, List<String> currentChilds)
                                throws Exception {
                            if(currentChilds.size() > 0){
                                this.notifyAll();
                            }
                        }
                    };
                    
                    zkClient.subscribeChildChanges(QUEUE_ROOT_PATH, listener);
                    
                    synchronized(listener){
                        try {
                            listener.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

        private String takeNode(String path){
            String value = zkClient.readData(QUEUE_ROOT_PATH + path);
            zkClient.delete(QUEUE_ROOT_PATH + path);
            return value;
        }
    }
}

 

 

3. 应用主备,主从

   所有服务器同时会在servers节点下注册一个临时节点。

   servers节点下所有服务争抢在zookeeper中注册master节点,未竞争成功者在zookeeper注册监听,若主服务失去连接,再次竞争。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值