关于动物园管理员锁定食谱的担忧

时间:2013-01-11 09:56:39

标签: apache-zookeeper

在阅读ZooKeeper的recipe for lock时,我感到困惑。似乎这个分布式锁的配方不能保证“任何两个客户认为它们持有相同锁定的任何快照”。但是由于ZooKeeper被如此广泛采用,如果参考文档中存在这样的错误,有人应该在很久以前就指出它,那么我误解了什么呢?

引用the recipe for distributed locks

  

     

全局同步的完全分布式锁,意味着在任何快照中没有两个客户端认为它们具有相同的锁。这些可以使用ZooKeeeper实现。与优先级队列一样,首先定义一个锁节点。

     
      
  1. 使用路径名“ locknode / guid-lock-”调用create(),并设置序列和短暂标志。
  2.   
  3. 在锁定节点上调用getChildren()而不设置监视标志(这对于避免群体效应很重要)。
  4.   
  5. 如果在步骤1中创建的路径名具有最低序列号后缀,则客户端具有锁定,客户端将退出协议。
  6.   
  7. 客户端调用exists(),并在锁定目录中的路径上设置监视标志,并使用下一个最低序列号。
  8.   
  9. 如果exists()返回false,请转到步骤2.否则,在转到步骤2之前,等待上一步中路径名的通知。
  10.   

考虑以下情况:

  • Client1成功获取锁定(在步骤3中),使用ZooKeeper节点“locknode / guid-lock-0”;
  • Client2创建节点“locknode / guid-lock-1”,无法获取锁定,现在正在观看“locknode / guid-lock-0”;
  • 后来,由于某种原因(比如网络拥塞),Client1无法按时向ZooKeeper集群发送心跳消息,但Client1仍在工作,错误地认为它仍然保持锁定。
  • 但是,ZooKeeper可能认为Client1的会话已超时,然后

    1. 删除“locknode / guid-lock-0”,
    2. 向Client2发送通知(或者可能先发送通知?),
    3. 但无法及时向Client1发送“会话超时”通知(例如,由于网络拥塞)。
  • Client2获取通知,转到第2步,获取它自己创建的唯一节点“”locknode / guid-lock-1“;因此,Client2假定它持有锁。
  • 但与此同时,Client1认为它持有锁。

这是一个有效的场景吗?

2 个答案:

答案 0 :(得分:15)

您描述的情景可能会出现。客户端1认为它具有锁定,但实际上其会话已超时,并且客户端2获取锁定。

ZooKeeper客户端库将通知客户端1其连接已断开连接(但客户端不知道会话已到期,直到客户端连接到服务器),因此客户端可以编写一些代码并假设他的锁定如果断断续续的时间已经过去了。但是使用锁的线程需要定期检查锁是否仍然有效,这本身就很有效。

答案 1 :(得分:0)

  

...但是,Zookeeper可能会认为client1的会话是超时的,然后......

来自Zookeeper文档:

  
      
  • 删除节点只会导致一个客户端唤醒   每个节点都由一个客户端监视。这样,你就避免了   牧群效应。
  •   
  • 没有投票或超时。
  •   

所以我认为你描述的问题不会出现。在我看来,如果创建它们的客户发生了某些事情,可能会有挂锁的风险,但是你所描述的场景不应该出现。