1. Redis分布式锁回顾
为了避免持有分布式锁的进程(线程)崩溃造成死锁的情况,上篇文章谈到的两种redis实现方案都为redis的key设置了定时失效。但是这种定时失效又会因为网路IO,GC影响造成在同一时间多个进程持有同一把锁的互斥性情况。这篇文章介绍一种新的分布式锁实现方案,也就是Zookeeper分布式锁方案,Zookeeper分布式锁的正确性远高于Redis分布式锁。
2. Zookeeper
ZooKeeper是一个开源的分布式协调服务,简单的说,zookeeper(zookeeper集群)作为分布式文件系统,它的作用是向外提供统一的一致性的视图。分布式系统由于受到CAP定理的约束,只能在一致性和可用性间做取舍,Zookeeper追求的是一致性。著名的RPC中间件Dubbo使用Zookeeper作为服务注册中心,Kafka使用Zookeeper维护meta数据。笔者在这篇文章中主要介绍使用Zookeeper实现分布式锁。在介绍Zookeeper分布式锁前,笔者先介绍Zookeeper三大关键特性,ZNode节点,Session心跳,Watcher机制。
2.1 ZNode
ZNode是Zookeeper的数据节点,在zookeeper中,ZNode节点有持久节点和临时节点两种节点。持久ZNode节点一旦被创建,除非执行了删除命令,否则持久节点就一直保留。客户端创建临时节点,一旦客户端断开和Zookeeper的连接,临时节点就会被删除。在Zookeeper分布式锁中,Zookeeper使用ZNode抽象分布式锁。
创建持久节点命令
create /per 123
创建持久顺序节点
create –s /per 123
创建临时节点
create –e /tmp 123
创建临时顺序节点
create –e –s /tmp 123
2.2 会话(Session)
客户端和zookeeper服务器通信后会建立一个会话,同时客户端和服务端会保持一条长连接,客户端需向服务端发送心跳告诉服务端自己仍然存活,如果超过sessionTimeout时间客户端没有发送心跳包,那么zookeeper服务端会认为客户端会话失效,同时会移除客户端创建的全部临时节点。
2.3 Watch机制
Watcher机制是Zookeeper提供的一种监听机制。客户端向zookeeper注册监听自己感兴趣的节点,一旦该节点状态发生了变化,Zookeeper就将节点变化的事件通过长连接告诉客户端。
3. 获取锁原理
上文提到,Zookeeper使用临时ZNode节点抽象分布式锁。进程在尝试获取zookeeper分布式锁的时候,如果当前锁空闲则直接获取锁,否则进行排队,同时监听ZNode节点。zookeeper因为采用了长连接心跳机制,一旦zookeeper监测到持有锁