如何处理 Apache Curator 分布式锁连接丢失
How to handle Apache Curator Distributed Lock loss of connection
假设我有两个分布式进程运行下面的代码使用 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");
}
其中 "do some things" 注释表示一次只需要由一个进程完成的多个语句。例如多次写入各种数据库。
这一切看起来都很好,直到 java 进程之一在获得锁后失去与 zookeeper 的连接。
根据文档:
It is strongly recommended that you add a ConnectionStateListener and
watch for SUSPENDED and LOST state changes. If a SUSPENDED state is
reported you cannot be certain that you still hold the lock unless you
subsequently receive a RECONNECTED state. If a LOST state is reported
it is certain that you no longer hold the lock.
如果我理解正确,在获取锁后的任何时候我都可能收到锁已丢失的通知,由于网络问题,此时其他进程可能已获取锁。如果那是真的,就不能保证在获得锁后你是唯一拥有锁的进程。我一次只能由一个进程执行的宝贵语句可能会与另一个进程交错。
我对上面的理解有误吗?如果是这样,请说明它的含义。如果我没有误解上述内容,如果不能保证独占访问,策展人锁有什么用?
这是分布式系统的普遍规律:网络和其他实例不稳定。如果您的实例与 ZooKeeper 整体失去联系,您将无法确定锁定节点的状态。这就是获得 SUSPENDED 连接状态更改的含义。在内部,ZooKeeper 已通知 Curator 与其 ZooKeeper 实例的连接已丢失。
这就是说,您可以 安全地假设在您的会话超时之前没有其他实例会获得锁定,因此您的操作在某种程度上取决于您。进一步注意,LOST 连接状态的含义在 Curator 3.x 中发生了变化。在 Curator 3.x 之前,LOST 状态仅表示您的重试策略已过期。在 3.x 中,Curator 现在在连接暂停时设置一个内部计时器,连接状态丢失意味着会话已过期。因此,对于许多应用程序,您可以安全地忽略 SUSPENDED 并仅在收到 LOST 时退出锁定。
抛开所有这些。即使在单个 JVM 中使用 JDK 锁,您也必须能够处理线程中断。让您的 Curator 应用程序锁定句柄 SUSPENDED/LOST 在语义上是一样的。
希望这对您有所帮助(注意我是 Apache Curator 的主要作者)
假设我有两个分布式进程运行下面的代码使用 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");
}
其中 "do some things" 注释表示一次只需要由一个进程完成的多个语句。例如多次写入各种数据库。
这一切看起来都很好,直到 java 进程之一在获得锁后失去与 zookeeper 的连接。
根据文档:
It is strongly recommended that you add a ConnectionStateListener and watch for SUSPENDED and LOST state changes. If a SUSPENDED state is reported you cannot be certain that you still hold the lock unless you subsequently receive a RECONNECTED state. If a LOST state is reported it is certain that you no longer hold the lock.
如果我理解正确,在获取锁后的任何时候我都可能收到锁已丢失的通知,由于网络问题,此时其他进程可能已获取锁。如果那是真的,就不能保证在获得锁后你是唯一拥有锁的进程。我一次只能由一个进程执行的宝贵语句可能会与另一个进程交错。
我对上面的理解有误吗?如果是这样,请说明它的含义。如果我没有误解上述内容,如果不能保证独占访问,策展人锁有什么用?
这是分布式系统的普遍规律:网络和其他实例不稳定。如果您的实例与 ZooKeeper 整体失去联系,您将无法确定锁定节点的状态。这就是获得 SUSPENDED 连接状态更改的含义。在内部,ZooKeeper 已通知 Curator 与其 ZooKeeper 实例的连接已丢失。
这就是说,您可以 安全地假设在您的会话超时之前没有其他实例会获得锁定,因此您的操作在某种程度上取决于您。进一步注意,LOST 连接状态的含义在 Curator 3.x 中发生了变化。在 Curator 3.x 之前,LOST 状态仅表示您的重试策略已过期。在 3.x 中,Curator 现在在连接暂停时设置一个内部计时器,连接状态丢失意味着会话已过期。因此,对于许多应用程序,您可以安全地忽略 SUSPENDED 并仅在收到 LOST 时退出锁定。
抛开所有这些。即使在单个 JVM 中使用 JDK 锁,您也必须能够处理线程中断。让您的 Curator 应用程序锁定句柄 SUSPENDED/LOST 在语义上是一样的。
希望这对您有所帮助(注意我是 Apache Curator 的主要作者)