假设我有两个分布式进程,运行下面的代码,这些代码使用zookeeper和curator进行共享锁定:

public static void main(String[] args) throws Exception {
    CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", new ExponentialBackoffRetry(500, 2));
    client.start();
    InterProcessMutex lock = new InterProcessMutex(client, "/12345");

    System.out.println("before acquire");
    lock.acquire();
    System.out.println("lock has been acquired");
    //do some things that need to be done in an atomic fashion
    lock.release();
    System.out.println("after release");
}

“做某事”注释表示多个语句,一次只需要一个进程即可完成。例如多次写入各种数据库。

直到获得锁的java进程之一失去与zookeeper的连接,一切似乎都还不错。

根据文档:



如果我正确理解这一点,则在获取锁后的任何时候,由于网络问题,我可能会收到有关该锁已丢失的通知,此时其他一些进程可能已经获取了该锁。如果是这样,则不能保证在获得锁之后,您是拥有该锁的唯一进程。我的宝贵的语句一次只能由一个进程执行,可能会与另一个进程交织在一起。

我是否误解了以上内容?如果是这样,请说明其含义。如果我没有误解上述内容,那么如果不能保证独占访问权,那么策展人锁又有什么用呢?

最佳答案

这是分布式系统的一般规则:网络和其他实例是不稳定的。如果您的实例与ZooKeeper集成失去联系,则无法确定锁定节点的状态。这就是获得挂起的连接状态更改的意思。在内部,ZooKeeper已通知Curator与它的ZooKeeper实例的连接已丢失。

这就是说,您可以放心地假设在 session 超时之前,没有其他实例会获得该锁,因此您所做的事情完全由您自己决定。还要注意,在Curator 3.x中LOST连接状态的含义已更改。在Curator 3.x之前,LOST状态仅表示您的重试策略已过期。在3.x中,Curator现在会在连接被挂起且LOST连接状态表示 session 已过期时设置一个内部计时器。因此,对于许多应用程序,您可以放心地忽略SUSPENDED并仅在收到LOST时退出锁。

除了所有这些。即使在单个JVM中使用JDK锁,您也必须能够处理线程中断。从语义上讲,让Curator应用程序锁处理SUSPENDED/LOST是同一件事。

希望这对您有所帮助(请注意,我是Apache Curator的主要作者)

10-04 18:30