zookeeper 实现分布式锁

1.zookeeper简介

zookeeper是一个分布式协调服务

应用场景:1.维护服务配置信息 2.分布式锁 3.集群管理 4.生成分布式唯一ID

2.zookeeper实现分布式锁的原理

大概步骤:当客户端需要获取锁,那么创建节点;释放锁,那么删除节点。

具体步骤:

  1. 客户端获取锁时,在lock节点下创建 临时顺序 节点。
  2. 然后获取lock节点下的所有子节点,客户端获取到所有的子节点之后,如果发现自己创建节点的序号最小,那么就认为客户端获取到了锁,使用完锁之后将该节点删除。
  3. 如果发现当前节点序号不是最小,说明当前客户端没有获取到锁,那么当前客户端启动一个监听器去监听比自己序号小的节点的删除事件,监听到删除事件之后回到步骤2继续执行。
    在这里插入图片描述
3.代码实现

上面的步骤是实现原理。使用apache开源的curator框架,我们只需要少量的代码即可。

  1. 导入maven依赖
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.0.1</version>
</dependency>
  1. 代码实现示例
/**
 * 测试使用zookeeper作为分布式锁
 */
public class TestDistributionLock {

    public static void main(String[] args) {
        // 创建资源
        Ticket ticket = new Ticket(15);

        // 模拟分布式环境
        new Thread(ticket, "1号窗口").start();
        new Thread(ticket, "2号窗口").start();
    }
}

class Ticket implements Runnable {

    private int ticketCount;

    private final InterProcessLock lock;

    public Ticket(int ticketCount) {
        this.ticketCount = ticketCount;
        // 重试策略
        RetryOneTime retryOneTime = new RetryOneTime(2 * 1000);
        // 创建zookeeper客户端
        CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.31.70:2181", retryOneTime);
        client.start();

        // 指定 /lock 作为锁的根节点
        lock = new InterProcessMutex(client, "/lock");
    }

    @Override
    public void run() {

        while( ticketCount > 0 ) {
            //获取锁
            try {
                lock.acquire();
                if (ticketCount > 0) {
                    // 为了演示效果,这里增加一个延迟
                    TimeUnit.MILLISECONDS.sleep(500);

                    ticketCount--;
                    System.out.println(Thread.currentThread().getName() + "售出1张票, 当前余票:" + ticketCount);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 释放锁
                try {
                    lock.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

运行结果:
zookeeper命令行客户端查看 /lock 节点

# 运行中 有两个有编号的顺序节点
[zk: localhost:2181(CONNECTED) 203] ls /lock
[_c_bd193c84-2598-4c36-9a89-a6a2c1056491-lock-0000000013, _c_e00572e7-d355-4388-8e49-54e8bf513bf6-lock-0000000014]
# 运行结束 节点为空
[zk: localhost:2181(CONNECTED) 204] ls /lock
[]

本地控制台

1号窗口售出1张票, 当前余票:14
2号窗口售出1张票, 当前余票:13
1号窗口售出1张票, 当前余票:12
2号窗口售出1张票, 当前余票:11
1号窗口售出1张票, 当前余票:10
2号窗口售出1张票, 当前余票:9
1号窗口售出1张票, 当前余票:8
2号窗口售出1张票, 当前余票:7
1号窗口售出1张票, 当前余票:6
2号窗口售出1张票, 当前余票:5
1号窗口售出1张票, 当前余票:4
2号窗口售出1张票, 当前余票:3
1号窗口售出1张票, 当前余票:2
2号窗口售出1张票, 当前余票:1
1号窗口售出1张票, 当前余票:0

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值