简述

在分布式环境下,为了保证在同一时刻只能有一个客户端对指定的数据进行访问,需要使用分布式锁技术。分布式锁实现主要以Zookeeper、Redis、MySQL这三种。

分布式锁的特点

  1. 互斥性:分布式锁需要保证在不同节点的不同线程的互斥。
  2. 可重入性:同一个节点上的同一个线程如果获取了锁之后那么也可以再次获取这个锁。
  3. 锁超时:和本地锁一样支持锁超时,防止死锁。
  4. 高效:高可用:加锁和解锁需要高效,同时也需要保证高可用防止分布式锁失效,可以增加降级。
  5. 支持阻塞和非阻塞:和ReentrantLock一样支持lock和trylock以及tryLock(long timeOut)。
  6. 支持公平锁和非公平锁(可选):公平锁的意思是按照请求加锁的顺序获得锁,非公平锁就相反是无序的。这个一般来说实现的比较少。

ZooKeeper分布式锁

image

利用ZooKeeper实现分布式锁,常用的实现方法是,所有希望获得锁的客户端都需要执行以下操作:

  1. 客户端连接ZooKeeper,调用create()方法在指定的锁节点(如/lock)下创建一个临时顺序节点。

    例如节点名为"zk",则第一个客户端创建的节点为“/lock/zk00000000”,第二个客户端创建的节点为"/lock/zk00000001"
  2. 客户端调用getChildren()方法查询锁节点/lock下的所有子节点列表,判断子节点列表中序号最小的子节点是否是自己创建的。如果是,则客户端获得锁,否则监听排在自己前一位的子节点的删除事件,若监听的子节点被删除,则重复执行此步骤,直至获得锁。
  3. 客户端执行业务代码。
  4. 客户端业务完成后,删除在ZooKeeper中对应的子节点以释放锁。

问题

一、上述第一步为什么要创建临时节点?

  1. 假如客户端A获得锁之后,客户端A所在的计算机宕机了,此时客户端A没有来得及主动删除子节点。如果创建的是永久节点,锁将永远不会被释放,其他进程拿不到该资源。
  2. 临时节点的好处:尽管客户端宕机了,但是ZooKeeper在一定时间内没有收到客户端的心跳则会认为回话失效,然后临时节点删除以释放锁。

二、未获取锁的客户端为什么要监听排在自己前一位的子节点的删除事件?

按照争夺锁的规则,每一轮锁的争夺取的都是序号最小的节点当序号最小的节点删除后,正常情况排在最小节点后一位的节点将获得锁。所以,客户端只需要监听自己前一位的节点即可,这样每当锁释放时,ZooKeeper只需要通知一个客户端,从而节省了网络带宽。若将监听事件设置在父节点/lock上,那么每次锁的释放将通知所有客户端。如果客户端数量庞大,会导致ZooKeeper服务器必须处理的操作数量激增,增加了ZooKeeper服务器的压力,同时很容易产生网络阻塞

以上内容整理自《Hadoop大数据技术开发实战》

eleven
4 声望0 粉丝