Zookeeper示例之分布式锁

上一篇 <<<Zookeeper示例之服务发现与治理
下一篇 >>>Zookeeper示例之节点事件监听


zookeeper实现分布式锁的原理就是多个节点同时在一个指定的节点下面创建临时会话顺序节点,谁创建的节点序号最小,谁就获得了锁,并且其他节点就会监听序号比自己小的节点,一旦序号比自己小的节点被删除了,其他节点就会得到相应的事件,然后查看自己是否为序号最小的节点,如果是,则获取锁。

1、模板方法

/**
 * 获得锁
 */
@Override
public void getLock() {
    //如果获得锁,就返回执行业务方法
    if(tryLock()){
        return;
    }
    //等待锁
    waitLock();
    //重新后去锁
    getLock();
}

/**
 * 释放锁
 */
@Override
public void unlock() {
    unlockImpl();
}

2、具体实现

/**
 * 创建zk实例,设置超时时间防止程序挂了一直处在等待状态
 */
private   ZkClient zkClient = new ZkClient("10.211.55.16:2181", 50000);

private String lockPath = "/lockPath";

private CountDownLatch countDownLatch = null;
@Override
protected boolean tryLock() {
    try {
        //创建临时节点成功,则执行业务
        zkClient.createEphemeral(lockPath);
        return true;
    }catch (Exception e){
        return false;
    }
}

@Override
protected void waitLock() {
    //创建监听机制,如果临时节点被删除,则继续执行后续的操作
    IZkDataListener iZkDataListener =  new IZkDataListener() {
        @Override
        public void handleDataChange(String s, Object o) throws Exception {
        }
        @Override
        public void handleDataDeleted(String s) throws Exception {
            countDownLatch.countDown();
        }
    };
    //订阅消息
    zkClient.subscribeDataChanges(lockPath, iZkDataListener);

    // 判断当前节点是否存在,如果存在就等待
    if (zkClient.exists(lockPath)) {
        //设置等待机制
        if (countDownLatch == null) {
            countDownLatch = new CountDownLatch(1);
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //取消订阅,防止多次订阅出现问题
    zkClient.unsubscribeDataChanges(lockPath,iZkDataListener);
}

@Override
protected void unlockImpl() {
    if(zkClient!=null) {
        zkClient.close();
        System.out.println(Thread.currentThread().getName() + "释放锁");
    }
}

3、使用方式

public class OrderService implements Runnable{

    private NumberUtil util = new NumberUtil();
    private MyLock lock = new ZkTemplateLock();
    @Override
    public void run() {
        getRealNumer();
    }

    private  void getRealNumer() {
        lock.getLock();
        String date = util.getNumber();
        System.out.println(Thread.currentThread().getName()+"-"+date);
        lock.unlock();
    }
}

推荐阅读:
<<<Zookeeper基础知识及应用场景
<<<Zookeeper如何实现分布式锁
<<<CAP理论和Base理论
<<<Zookeeper选举的策略
<<<为什么Zookeeper集群节点一定要是奇数
<<<Zookeeper在后期新增zk节点时如何提高选举效率问题
<<<Zookeeper如何保证节点一致性问题
<<<Zookeeper的Zab一致性协议原理
<<<Zookeeper实现哨兵选举机制
<<<Zookeeper示例之访问权限控制
<<<Zookeeper示例之服务发现与治理
<<<Zookeeper示例之节点事件监听
<<<Zookeeper示例之集群请求
<<<Linux环境安装Zookeeper
<<<Zookeeper配置文件介绍
<<<Zookeeper常见问题
<<<Eureka与Zookeeper有啥区别?
<<<Zookeeper常用命令

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容