Apache zookeeper 为什么我需要使用curator而不是zookeeper本机API作为分布式锁?

Apache zookeeper 为什么我需要使用curator而不是zookeeper本机API作为分布式锁?,apache-zookeeper,apache-curator,Apache Zookeeper,Apache Curator,我们的项目严重依赖分布式锁。我知道馆长提供了几种锁。我的问题是,我可以将创建节点用作互斥对象吗 CuratorFramework zkClient = zookeeperConnectionProvider.getZkClientForJobDistributeLock(); try { zkClient.create() .creatingParentsIfNeeded()

我们的项目严重依赖分布式锁。我知道馆长提供了几种锁。我的问题是,我可以将创建节点用作互斥对象吗

CuratorFramework zkClient = zookeeperConnectionProvider.getZkClientForJobDistributeLock();
            try {
                zkClient.create()
                        .creatingParentsIfNeeded()
                        .withMode(CreateMode.EPHEMERAL)
                        .forPath("/" + job.getIdentifier().jobNodeString());
                LOGGER.info(String.format("create node in zookeeper [%s]", job.getIdentifier().jobNodeString()));
            } catch (Exception e) {
                LOGGER.info(String.format("create job instance node in zookeeper failed [%s], reason [%s]",
                        job.getIdentifier().jobNodeString(),
                        e.getClass().getCanonicalName()));
                return NO_WORK;
            }
当第一个进程成功创建时,第二个进程将获得
NodeExistsException
异常。如果这样不行,我想知道原因

我认为反对按您的建议执行的第一个反对意见是,很难阅读/理解代码,请将其与以下内容进行比较:

InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(client, path);
lock.acquire();
另一个原因是您通常使用锁来阻止线程,直到另一个线程释放锁,这样您就可以编写如下所示的代码:

//do normal work
...
lock.acquire();
//do critical single threaded work
...
lock.release();
//back to normal work
...
这在您的代码中是完全可能的,但在这里它是为您创建的



使用已经实现的锁而不是编写自己的锁还有很多原因,但这主要归结为:“为什么要重新发明轮子?”

我认为反对按您的建议执行的第一个原因是,很难阅读/理解代码,请将其与:

InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(client, path);
lock.acquire();
另一个原因是您通常使用锁来阻止线程,直到另一个线程释放锁,这样您就可以编写如下所示的代码:

//do normal work
...
lock.acquire();
//do critical single threaded work
...
lock.release();
//back to normal work
...
这在您的代码中是完全可能的,但在这里它是为您创建的



使用已经实现的锁而不是编写自己的锁还有很多原因,但这主要归结为:“为什么要重新发明轮子?”

谢谢Petter。我需要的是类似互斥的东西,但是失败的进程不需要等到成功发布。我原以为zookeeper中的命名节点可以,但我发现它根本不起作用。最后我转向进程间互斥。一开始不使用它的原因是,我读了一些文档,知道它在zookeeper中创建了几个节点,并且最小索引将获得锁。所以我认为一个节点可能更有效。之后我做了一些实验:进程A在zookeeper中创建一个节点并保持连接,然后进程B删除该节点,我得到一个非节点异常。如果进程A与zookeeper服务器断开连接,则进程B可以正确删除它(ps:节点类型为CreateMode.Persistent)。不同连接之间是否存在某种“隔离”机制?如果不想等待锁定,可以使用:Boolean hasLock=lock.acquire(1,TimeUnit.millists);我不确定您是否可以使用0,但这只会等待1毫秒的锁定,因此它不会使您的代码慢很多。哦,如果“hasLock”是假的,你就没有得到锁。谢谢你,皮特。我需要的是类似互斥的东西,但是失败的进程不需要等到成功发布。我原以为zookeeper中的命名节点可以,但我发现它根本不起作用。最后我转向进程间互斥。一开始不使用它的原因是,我读了一些文档,知道它在zookeeper中创建了几个节点,并且最小索引将获得锁。所以我认为一个节点可能更有效。之后我做了一些实验:进程A在zookeeper中创建一个节点并保持连接,然后进程B删除该节点,我得到一个非节点异常。如果进程A与zookeeper服务器断开连接,则进程B可以正确删除它(ps:节点类型为CreateMode.Persistent)。不同连接之间是否存在某种“隔离”机制?如果不想等待锁定,可以使用:Boolean hasLock=lock.acquire(1,TimeUnit.millists);我不确定您是否可以使用0,但这只会等待1毫秒的锁定,因此它不会使您的代码慢很多。哦,如果“hasLock”是假的,你就没有得到锁。