持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
回顾
- 上文我们通过redis实现了我们的分布式锁,但是如果redis挂了怎么办呢?如果需要保证锁服务的高可用,可以对Redis做高可用方案:Redis集群+主从切换。目前都有比较成熟的解决方案。
基于Zookeeper实现分布式锁
-
zookeeper的存储结构是一颗树。同时它具有如下特征
-
持久节点(PERSISTENT):默认的节点类型。创建节点的客户端与zookeeper断开连接后,该节点依旧存在 。
-
持久节点顺序节点(PERSISTENT_SEQUENTIAL): 所谓顺序节点,就是在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号:
-
临时节点(EPHEMERAL) :和持久节点相反,当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。
-
临时顺序节点(EPHEMERAL_SEQUENTIAL) :顾名思义,临时顺序节点结合和临时节点和顺序节点的特点:在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与Zookeeper断开连接后,临时节点会被删除。
-
注意因为zookeeper中节点是具有顺序性质的,所以当我们释放锁之后就不需要向m y s q l,reids那样线程争抢式唤醒了。只需要按照节点的顺序进行有序唤醒这样极大的节省了我们cpu的调度。
加锁
首先,在Zookeeper当中创建一个持久节点hello。当第一个客户端想要获得锁时,需要在hello这个节点下面创建一个临时顺序节点 Lock1。
之后,Client1查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock1是不是顺序最靠前的一个。如果是第一个节点,则成功获得锁。
这时候,如果再有一个客户端 Client2 前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock2。
于是,Client2向排序仅比它靠前的节点Lock1注册Watcher,用于监听Lock1节点是否存在。这意味着Client2抢锁失败,进入了等待状态。