在阅读ZooKeeper的recipe for lock时,我感到困惑。似乎这个分布式锁的配方不能保证“任何两个客户认为它们持有相同锁定的任何快照”。但是由于ZooKeeper被如此广泛采用,如果参考文档中存在这样的错误,有人应该在很久以前就指出它,那么我误解了什么呢?
引用the recipe for distributed locks:
锁
全局同步的完全分布式锁,意味着在任何快照中没有两个客户端认为它们具有相同的锁。这些可以使用ZooKeeeper实现。与优先级队列一样,首先定义一个锁节点。
- 使用路径名“ locknode / guid-lock-”调用create(),并设置序列和短暂标志。
- 在锁定节点上调用getChildren()而不设置监视标志(这对于避免群体效应很重要)。
- 如果在步骤1中创建的路径名具有最低序列号后缀,则客户端具有锁定,客户端将退出协议。
- 客户端调用exists(),并在锁定目录中的路径上设置监视标志,并使用下一个最低序列号。
- 如果exists()返回false,请转到步骤2.否则,在转到步骤2之前,等待上一步中路径名的通知。
醇>
考虑以下情况:
但是,ZooKeeper可能认为Client1的会话已超时,然后
这是一个有效的场景吗?
答案 0 :(得分:15)
您描述的情景可能会出现。客户端1认为它具有锁定,但实际上其会话已超时,并且客户端2获取锁定。
ZooKeeper客户端库将通知客户端1其连接已断开连接(但客户端不知道会话已到期,直到客户端连接到服务器),因此客户端可以编写一些代码并假设他的锁定如果断断续续的时间已经过去了。但是使用锁的线程需要定期检查锁是否仍然有效,这本身就很有效。
答案 1 :(得分:0)
...但是,Zookeeper可能会认为client1的会话是超时的,然后......
来自Zookeeper文档:
- 删除节点只会导致一个客户端唤醒 每个节点都由一个客户端监视。这样,你就避免了 牧群效应。
- 没有投票或超时。
所以我认为你描述的问题不会出现。在我看来,如果创建它们的客户发生了某些事情,可能会有挂锁的风险,但是你所描述的场景不应该出现。