持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情
zookeeper实现公平锁
zookeeper实现分布式锁的方式是依托于zookeeper本身提供的功能:临时有序节点实现,大概思路:
- 分布式客户端要加分布式锁时,向zookeeper中指定目录下添加一个临时有序节点,添加完成后,获取指定目录下的所有节点,判断当前创建的节点序号是否是所有节点中序号最小的值,如果是的话,则持有锁,如果不是的话,则进行自旋/阻塞等待,并向zookeeper注册一个监听时间,监听最小序号节点的变化
- 此时假设已有客户端持有锁,另一个客户端同第一步,连接zookeeper后先行创建一个临时有序节点,创建指定的目录和第一步中指定的目录相同,创建完成后执行相同的操作,检测是否是序号最小值,判断是否持有锁或者阻塞,并且注册监听事件
- 当持有锁的客户端执行完操作后,删除当前客户端创建的临时有序节点,此时由于节点被删除,监听此节点变化的其他客户端,会收到响应事件,此时再做出响应,重新获取指定目录下的所有节点,再次进行最小值判断,是则持有锁
此实现方式的思想很简单,但是需要注意的点有几个:
- 对于同一个业务而言,需要加锁的目录要提前指定,例如:/lock/business1
- 在客户端获取锁失败后,需要注册监听事件,例如此时是节点为N00001的客户端持有锁,监听事件就是N00001的节点状态变化
- 当客户端发生异常,连接断开后,临时有序节点就会被删除
zookeeper实现非公平锁
zookeeper实现非公平锁的思路和公平锁的思路大致一样,不一样的是每个客户端创建额节点非临时有序节点,而是创建临时节点,每个客户端对于相同的业务而言,创建的都是相同目录的同名节点,创建成功并且是自己创建的,才能够获取锁,非自己创建的节点,则一样会注册监听事件,并阻塞等待。
总结
两种方式都是利用的zookeeper节点的特性,并且zookeeper的高可用性,可以很好的保证业务的稳定性,故而zookeeper是实现分布式锁的很好方式,并且目前已有线程的zookeeper框架(curator),内部实现了上述逻辑,使用时可以方便的调用方法即可。