Zookeeper实现分布式锁

1.Zookeeper实现分布式锁原理

          使用zookeeper创建临时序列节点来实现分布式锁,适用于顺序执行的程序,大体思路就是创建临时序列节点,找出最小的序列节点,获取分布式锁,程序执行完成之后此序列节点消失,通过watch来监控节点的变化,从剩下的节点的找到最小的序列节点,获取分布式锁,执行相应处理,依次类推……
Maven依赖

<dependencies>
	<dependency>
		<groupId>com.101tec</groupId>
		<artifactId>zkclient</artifactId>
		<version>0.10</version>
	</dependency>
</dependencies>

创建接口

public interface EtLock {
    /**
     *
     * 获取锁
     */
    void getLock();

    /**
     * 释放锁
     */
    void unLock();
}

创建抽象类

/**
 * @author Administrator
 */
public abstract class AbstractZookeeperLock implements EtLock {
    /**
     * zk连接地址
     */
    private static final String CONNECTING = "192.168.223.120:2181";

    /**
     * 创建zk连接
     */
    protected ZkClient zkClient = new ZkClient(CONNECTING);

    /**
     * 创建临时节点名称
     */
    protected static final String PATH = "/lock";

    @Override
    public void getLock() {
        if (tryLock()) {
            System.out.println("获取lock锁的资源...");
        } else {
            waitLock();
            getLock();
        }
    }

    /**
     * 尝试获取锁
     *
     * @return false or true
     */
    abstract boolean tryLock();

    /**
     * 等待锁资源
     */
    abstract void waitLock();

    @Override
    public void unLock() {
        if (zkClient != null) {
            zkClient.close();
            System.out.println("释放锁资源...");
        }
    }
}

子类继承抽象类

public class ZookeeperDistrbuteLock extends AbstractZookeeperLock{
    private CountDownLatch countDownLatch = null;
    @Override
    boolean tryLock() {
        try {
            // 创建成功说明获取到锁资源了,返回true
            zkClient.createEphemeral(PATH);
            return true;
        } catch (Exception e) {
            // 创建失败了,说明没有获取到锁,返回false
            return false;
        }
    }

    @Override
    void waitLock() {
        IZkDataListener iZkDataListener = new IZkDataListener() {
            @Override
            public void handleDataChange(String s, Object o) throws Exception {

            }

            @Override
            public void handleDataDeleted(String s) throws Exception {
                // 唤醒被等待的线程
                if (countDownLatch != null) {
                    countDownLatch.countDown();
                }
            }

        };
        // 注册监听事件
        zkClient.subscribeDataChanges(PATH, iZkDataListener);
        // 判断节点是否存在
        if (zkClient.exists(PATH)) {
            countDownLatch = new CountDownLatch(1);
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {

            }
        }
        // 为了不影响后续节点的运行要删除监听事件,waitLock()会调用多次,多次监听,所以要用完就删除监听
        zkClient.unsubscribeDataChanges(PATH, iZkDataListener);
    }
}

验证结果

public class OrderService implements Runnable{
    private OrderNumGenerator orderNumGenerator = new OrderNumGenerator();
    private EtLock lock = new ZookeeperDistrbuteLock();
    @Override
    public void run() {
        getNumber();
    }
    public void getNumber() {
        try {
            lock.getLock();
            String number = orderNumGenerator.getNumber();
            System.out.println(Thread.currentThread().getName() + ",生成订单ID:" + number);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unLock();
        }
    }
    public static void main(String[] args) {
        System.out.println("####生成唯一订单号###");
//		OrderService orderService = new OrderService();
        for (int i = 0; i < 100; i++) {
            new Thread( new OrderService()).start();
        }
    }
}

总结:

实现思路:分布式锁的思路我们可以类比Lock保证多线程安全实现思路,获取锁和释放锁两个方法,我们用zookeeper创建临时节点,如果创建成功说明获取到锁,如果创建失败说明没有获取到锁,我们就要等待锁的释放然后再去获取锁。伪代码实现,创建临时节点成功,获取到锁,没有成功时,我们需要监听临时节点是否被删除,删除的时候,我们就去获取锁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值