《zookeeper》之分布式锁
排它锁
定义锁:
通过zookeeper上的数据节点来表示一个锁,例如 /exclusive_lock/lock 节点就可以定义为一个锁。
获取锁:
在获取排它锁时,所有的客户端都试图在/exclusive_lock节点下创建临时子节点/exclusive_lock/lock
1)只有一个客户端能够创建成功,那么就认为该客户端获取了锁。
2)同时,没有获取到锁的客户端需要到/exclusive_lock 节点上注册一个子节点变更的watcher监听,以便实时的获取到lock节点的变更情况。
释放锁:
在定义锁的时候,/exclusive_lock/lock是一个临时节点,在以下情况下,会释放锁:
1)当前获取锁的客户端发生宕机,zookeeper上的这个临时节点就会被移除
2)正常执行完业务逻辑后,客户端就会主动将自己创建的临时节点删除
移除lock节点,zookeeper就会通知所有在/exclusive_lock节点上注册子节点变更watcher监听的客户端。
这些客户端在接受到通知后,再次重新发起分布式锁的获取。
共享锁
不同的事务可以同时对同一个数据对象进行读取操作,而更新操作必须在没有任何事务进行读写操作的情况下进行。
定义锁:
通过zookeeper的数据节点来表示一个锁,类似于 /shared_lock/[hostname]-请求类型-序号 的临时顺序节点。
获取锁:
在需要获得锁的时候,所有的客户端都会到、shared_lock这个节点下面创建一个临时顺序节点:
如果是读请求,就创建/shared_lock/[hostname]-R-000000001
如果是写请求,就创建/shared_lock/[hostname]-W-000000001
判断读写顺序:
1)获取/shared_lock节点下所有的子节点,并对该节点注册 子节点变更 的watcher 监听。
2)确定自己的节点序号在所有子节点中的顺序
3)读请求:如果没有比自己序号小的子节点,或者比自己序号小的子节点都是读请求,表明自己已经成功获取到了共享锁。
如果比自己序号小的子节点有写请求,进入等待。
写请求: 如果自己不是序号最小的子节点,进入等待。
4)接收到watcher通知后,重复步骤1)。
释放锁:同上
分布式队列
定义队列:
通过zookeeper的数据节点来表示一个队列,类似于 /queue_info/[hostname]-序号 的临时顺序节点。
1)获取/queue_info节点下所有的子节点
2)确定自己的节点序号在所有子节点中的顺序
3)如果自己不是序号最小的子节点,进入等待。同时向比自己序号小的最后一个节点注册watcher监听。
4)接收到watcher通知后,重复步骤1)。
分布式屏障
1)获取/queue_barrier节点的数据内容:10
2)获取/queue_barrier节点下的所有子节点,即获取队列中所有元素,同时注册对子节点列表变更watcher监听
3)统计子节点个数
4)如果子节点个数还不满足10,进入等待
5)接收到watcher通知后,重复步骤2.