• ZooKeeper系列:实现分布式锁


    锁是为了在多线程的场景中保证数据安全而增加的一种手段,Java中常用的有CountdownLatch,ReentrantLock等单应用中的锁,在现在处处都是分布式的场景需求下就不能满足了,所以就出现了分布式锁。

    不同的物理节点有各自的线程,但是他们会访问同一个资源,但是不允许同一时刻访问,所以就有了分布式锁

    例如

    我们可以通过数据库编写sql来实现分布式锁,但是这种在高并发下性能会出问题,

    还有常用的redis实现分布式锁,这个是我们用的最多的一种高性能高并发的实现方式。

    今天介绍的一种是通过中间件zookeeper实现分布式锁,也是支持高性能高并发的。

    想想实现一个锁想到哪些关键点 ?

    争抢锁:只有一个人可以获取锁
    
    获得锁的节点挂了,临时节点 会自动释放
    
    获得锁的人,可以主动释放锁
    
    锁被释放,删除 其他人怎么知道
    
    主动轮训,监听心跳:存在延迟,节点多的情况话压力很大。
    
    复制代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    根据zk的节点看看是否满足锁

    创建持久化节点

    zk是创建节点保存数据的,相同节点只允许创建一次,所以我们可以通过成功创建节点实现获取锁的情况。

    关键代码

    zk.create("/lock",  threadId.getBytes() , ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    复制代码
    
    • 1
    • 2

    结果:

    如图只有一个线程获取锁,其他线程都出现异常:NodeExists for /lock ,可以保证同一时刻只有一个线程获取锁。然后获得锁的线程逻辑执行结束后应该删除锁。

    存在的问题:如果线程崩溃了,锁就无法释放了,最终导致死锁

    持久化节点不行,持久化顺序节点自然也不行了

    创建临时节点

    临时节点:在客户端断开连接的时候就会自动删除

    关键代码:

    zk.create("/lock",  threadId.getBytes() , ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    
    • 1

    CreateMode.EPHEMERAL意思就是创建临时节点 ,也就是当线程崩溃,无法主动释放锁的时候,会自动删除,避免死锁。

    但是

    还存在的问题:没有获取锁的线程会出现错误,则需要不断重试,通过死循环直到获取锁。

  • 相关阅读:
    [附源码]SSM计算机毕业设计郴职图书馆管理系统JAVA
    哈希表(Hash Table)介绍
    成功解决 java.lang.NumberFormatException
    Mysql查询训练——50道题
    【2】SM2验签工具和RSA验签工具
    python unittest测试报告生成
    Python网络编程之网络基础
    太阳 & IT
    css实现鼠标悬停时元素的显示与隐藏
    Spring IOC源码:obtainFreshBeanFactory 详解(中)
  • 原文地址:https://blog.csdn.net/Huangjiazhen711/article/details/127767004