加入收藏 | 设为首页 | 会员中心 | 我要投稿 宁德站长网 (https://www.0593zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

为什么Zookeeper天生就是一副分布式锁的胚子?

发布时间:2020-03-15 20:31:17 所属栏目:MySql教程 来源:站长网
导读:副标题#e# 【金融特辑】光大****科技部DBA女神带你从0到1揭秘MGR 什么是分布式锁?分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。 图片来自 Pexels 如果不同的系统或是同一个系统的不同主机之间共享了

       String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return 

redis.call('del', KEYS[1]) else return 0 end"; 

       Object result = jedis.eval(script, Collections.singletonList(lockKey), 

Collections.singletonList(requestId)); 

       if (result.equals(1L)) { 

           return true; 

       return false; 

  } 

Zookeeper 的分布式锁

Zookeeper 分布式锁实现原理

理解了锁的原理后,就会发现,Zookeeper 天生就是一副分布式锁的胚子。

首先,Zookeeper 的每一个节点,都是一个天然的顺序发号器。

在每一个节点下面创建子节点时,只要选择的创建类型是有序(EPHEMERAL_SEQUENTIAL 临时有序或者 PERSISTENT_SEQUENTIAL 永久有序)类型,那么,新的子节点后面,会加上一个次序编号。

这个次序编号,是上一个生成的次序编号加 1,比如,创建一个用于发号的节点“/test/lock”,然后以他为父亲节点,在这个父节点下面创建相同前缀的子节点。

假定相同的前缀为“/test/lock/seq-”,在创建子节点时,同时指明是有序类型。

如果是第一个创建的子节点,那么生成的子节点为 /test/lock/seq-0000000000,下一个节点则为 /test/lock/seq-0000000001,依次类推,等等。

为什么Zookeeper天生就是一副分布式锁的胚子?

其次,Zookeeper 节点的递增性,可以规定节点编号最小的那个获得锁。

一个 Zookeeper 分布式锁,首先需要创建一个父节点,尽量是持久节点(PERSISTENT 类型),然后每个要获得锁的线程都会在这个节点下创建个临时顺序节点,由于序号的递增性,可以规定排号最小的那个获得锁。

所以,每个线程在尝试占用锁之前,首先判断自己是排号是不是当前最小,如果是,则获取锁。

第三,Zookeeper 的节点监听机制,可以保障占有锁的方式有序而且高效。

每个线程抢占锁之前,先抢号创建自己的 ZNode。同样,释放锁的时候,就需要删除抢号的 Znode。

抢号成功后,如果不是排号最小的节点,就处于等待通知的状态。等谁的通知呢?不需要其他人,只需要等前一个 Znode 的通知就可以了。

当前一个 Znode 删除的时候,就是轮到了自己占有锁的时候。第一个通知第二个、第二个通知第三个,击鼓传花似的依次向后。

Zookeeper 的节点监听机制,可以说能够非常完美的,实现这种击鼓传花似的信息传递。

具体的方法是,每一个等通知的 Znode 节点,只需要监听 linsten 或者 watch 监视排号在自己前面那个,而且紧挨在自己前面的那个节点。

只要上一个节点被删除了,就进行再一次判断,看看自己是不是序号最小的那个节点,如果是,则获得锁。

为什么说 Zookeeper 的节点监听机制,可以说是非常完美呢?

一条龙式的首尾相接,后面监视前面,就不怕中间截断吗?比如,在分布式环境下,由于网络的原因,或者服务器挂了或者其他的原因,如果前面的那个节点没能被程序删除成功,后面的节点不就永远等待么?

其实,Zookeeper 的内部机制,能保证后面的节点能够正常的监听到删除和获得锁。

在创建取号节点的时候,尽量创建临时 Znode 节点而不是永久 Znode 节点。

一旦这个 Znode 的客户端与 Zookeeper 集群服务器失去联系,这个临时 Znode 也将自动删除。排在它后面的那个节点,也能收到删除事件,从而获得锁。

说 Zookeeper 的节点监听机制,是非常完美的。还有一个原因。Zookeeper 这种首尾相接,后面监听前面的方式,可以避免羊群效应。

所谓羊群效应就是每个节点挂掉,所有节点都去监听,然后做出反映,这样会给服务器带来巨大压力,所以有了临时顺序节点,当一个节点挂掉,只有它后面的那一个节点才做出反映。

Zookeeper 分布式锁实现示例

Zookeeper 是通过临时节点来实现分布式锁:

terruptedException e) { 

           e.printStackTrace(); 

      } 

       System.out.println("*********业务方法结束************n"); 

 

  } 

 

   // 这里使用@Test会报错 

   public static void main(String[] args) { 

       // 定义重试的侧策略 1000 等待的时间(毫秒) 10 重试的次数 

       RetryPolicy policy = new ExponentialBackoffRetry(1000, 10); 

 

       // 定义zookeeper的客户端 

       CuratorFramework client = CuratorFrameworkFactory.builder() 

(编辑:宁德站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读