ZooKeeper分布式锁应用
前言
前些天,学习过ZooKeeper一些基本知识,现在了解下有关ZooKeeper在分布式锁上的实现。
分布式锁
分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或者是同系统不同主机之间共享了一个或者一组资源,当访问这些资源的时候,需要通过一些互斥手段来防止彼此之间的干扰。以保证数据一致性。
排他锁实现
排他锁:又称为写锁或独占锁,如果某个事务T对数据对象O加上排他锁,则在整个加锁期间,只允许事务T对O进行读取和更新操作,其他事务都不能对其加任何锁,直到释放了排他锁。
详细过程
获取锁:所有需要获取排他锁的客户端试图通过调用Zookeeper中的
create()
接口在/exclusive_lock
节点下创建临时子节点/exclusive_lock/lock
,创建成功的那个客户端即为获得到排他锁,而其他客户端则在/exclusive_lock
节点上注册一个子节点变更的Watcher监听,以便监听lock节点的变更通知。释放锁:因为在上获取锁中创建的是临时节点,所有当出现下面情况都会被释放
- 当前获取锁的客户端机器宕机,则ZooKeeper上的这个临时节点被删除。
- 正常执行完业务逻辑后,客户端就会主动将自己创建的临时节点删除。
当
lock
节点被删除,所有在/exclusive_lock
节点上注册监听Watcher客户端再次发起分布式锁的获取。
共享锁实现
共享锁:又称为读锁。如果事务T对数据对象O加上了共享锁,那么当前事务只能对O进行读取操作,其他事务也只能对这个数据对象加共享锁,直到该数据对象上的所有共享锁都被释放。
详细过程
获取锁:所有客户端都会到
/shared_lock
这个节点下面创建一个临时顺序节点,如果读请求,则创建/shared_lock/192.168.0.1-R-0000000001
的节点。如果写请求,则创建/shared_lock/192.168.0.1-W-0000000001
的节点。(前面一串名字可以自定义,方便快速定位那一台服务器、啥操作,具体按照业务需求吧)判断读写顺序(根据共享锁定义,不同事务都可以对同一个数据进行读取操作,而更新操作必须在当前没有任何事务进行读写操作的情况下进行。)
- 创建完节点后,获取
/share_lock
节点下的所有子节点,并对该节点注册子节点变更的Watcher监听。 - 确定自己的节点序号在所有子节点中顺序
- 对于读请求:
- 如果没有比自己序号小的子节点,或者所有比自己序号小的子节点都是读请求,那表明自己已经成功获取到了共享锁,开始执行读取逻辑。
- 如果比自己序号小的子节点有写请求,则需要进入等待。
- 对于写请求:
- 如果自己不是序号最小的子节点,则需要进入等待。
- 接收到Watcher后,删除该节点,继续下一个节点。
- 创建完节点后,获取
释放锁
- 当前获取锁的客户端机器宕机,则ZooKeeper上的这个临时节点被删除。
- 正常执行完业务逻辑后,客户端就会主动将自己创建的临时节点删除。