基于永久序号节点

1 客户端调用 create() 方法创建父节点 locknode 与其子节点 locknode/guid-lock-,注意所创建节点的类型需要设置为 EPHEMERAL_SEQUENTIAL。

2 客户端调用 getchildren(“locknode”) 方法来获取所有已经创建的子节点,同时在这些子节点上注册 Watcher。

3 客户端获取了所有子节点之后,如果发现自己在步骤1中创建的子节点是所有子节点中序号最小的,就说明自己已经获取到了锁。

4 如果客户端在步骤 3 中发现自己创建的子节点并非是所有子节点中序号最小的, 说明自己还没有获取到锁,需要等待,直至接到 Watcher 发送的子节点变更通知(即其他客户端释放锁)之后,オ能再获取一次子节点,以判断自己是否获取到了锁。

SpringBoot整合Zookeeper集群实现分布式锁 zookeeper分布式事务锁_分布式

和Redis分布式锁的优劣势

优点:不存在redis的超时、数据同步(zookeeper是同步完以后才返回)、主从切换(zookeeper主从切换的过程中服务是不可用的)的问题,可靠性很高。

缺点:依赖中间件,保证了可靠性的同时牺牲了一部分效率(但是依然很高)。性能不如redis。

=========================================================================

Zookeeper对于事务性的支持

它对于事务性的支持主要依赖于四个函数,zoo_create_op_init zoo_delete_op_init zoo_set_op_init以及zoo_check_op_init。每一个函数都会在客户端初始化一个operation,客户端程序有义务保留这些operations。当准备好一个事务中的所有操作后,可以使用zoo_multi来提交所有的操作,由zookeeper服务来保证这一系列操作的原子性。也就是说只要其中有一个操作失败了,相当于此次提交的任何一个操作都没有对服务端的数据造成影响。Zoo_multi的返回值是第一个失败操作的状态信号。

Zookeeper通过版本号来保证操作的实效性。zoo_set的最后一个形参就是version number。如果提交的数和服务端在该节点的版本号对不上,那么此次设值操作就失败了。这可以解决这样的情况:client1.get, client2.get, client2.set, client1.set。从client1的角度出发,set和get之前操作的变量值已经发生改变了,zookeeper非常负责的保证的最后一次set将不会成功,客户端可以重新get, set一次。