Java Zookeeper API 奇怪的 ZNode 行为。无法正确删除 ZNode。有意想不到的效果
Java Zookeeper API weird ZNode behavior. Unable to delete ZNode properly. It has unexpected results
我正在尝试创建一个永久性 ZNode 并存储我已处理的特定文件的行数。创建就像它应该的那样工作,从节点读取数据也是如此,但是如果它在相同的代码中,删除就不起作用。我会解释我的意思。
我创建了函数:
setOrCreateFileCheckpoint(fileName: String, lineNumber: Int) :- 检查 ZNode 是否存在,如果不存在则创建它,并将存储的值设置为 行号
getFileCheckpoint(fileName: String) :- returns ZNode 中存储的值
deleteFileCheckpoint(fileName: String) :- 删除 ZNode
下面是所有三个的代码:
/*
updates or creates a checkpoint for a file being processed
*/
def setOrCreateFileCheckpoint(fileName: String, lineNumber: Int): Unit =
{
val fileCheckpointPath = checkpointPoolPath + "/" +fileName
val zk = getZookeeper
val zkCuratorClient = getZookeeperCuratorClient
if ( zk.exists(fileCheckpointPath, false) == null)
{
val node = new PersistentNode(zkCuratorClient, CreateMode.PERSISTENT, false, fileCheckpointPath, lineNumber.toString.getBytes())
node.start()
}
else
zk.setData(fileCheckpointPath, lineNumber.toString.getBytes(), -1)
}
/*
gets checkpoint for a file
*/
def getFileCheckpoint(fileName: String): Int =
{
val fileCheckpointPath = checkpointPoolPath + "/" +fileName
val zk = getZookeeper
val zkCuratorClient = getZookeeperCuratorClient
if ( zk.exists(fileCheckpointPath, false) != null)
new String(zk.getData(fileCheckpointPath, false, null)).toInt
else
0
}
/*
deletes the file checkpoint so that we don't keep accumulating zNodes on the zookeeper
*/
def deleteFileCheckpoint(fileName: String): Unit =
{
val fileCheckpointPath = checkpointPoolPath + "/" +fileName
val zk = getZookeeper
if ( zk.exists(fileCheckpointPath, false) == null)
{
throw RuntimeException("Trying to delete checkpoint that doesn't exist for file: " + fileName)
}
else
{
/*println(zk.exists(fileCheckpointPath, false).getVersion)
zk.delete(fileCheckpointPath, zk.exists(fileCheckpointPath, false).getVersion)*/
deleteChildren(zk, fileCheckpointPath, true)
}
}
以下是我正在测试并感到困惑的代码:
ZookeeperUtility.setOrCreateFileCheckpoint("file1", 2000) //let's call it cre1
println(ZookeeperUtility.getFileCheckpoint("file1")) //let's call it get1
ZookeeperUtility.deleteFileCheckpoint("file1") //let's call it del1
println("del1")
ZookeeperUtility.deleteFileCheckpoint("file1") //let's call in del2
println("del2")
运行 1:
第一步:我运行上面显示的代码
结果:del2遇到错误
第 2 步:注释掉 cre1 并再次 运行 代码
结果:获取节点,给出正确的值,因为在 del2 上遇到结果错误。这令人难以置信。我不明白为什么。该节点应该被删除。
第 3 步:cre1 仍然注释,与上一步相同,运行 代码再次
结果:节点不存在在 get1 处给出 0,这意味着节点不存在。在 del1 处遇到错误。这是在第 2 步中应该发生的事情
运行2:
第一步:注释掉del2,运行代码
结果:创建节点,获取正确数据,正常退出
第二步:注释掉cre1,运行代码
结果:从应该删除的节点中获取值 2000。正常退出
第三步:运行再次使用与第二步相同的代码
结果:获取 0,del1 时遇到错误。
如果我 运行 代码一次一步,如果我只在一个 运行 中创建,则只在下一个 运行 中获取并且只在 运行 中删除=] 之后,一切正常。我快要拔头发了。
P.S。代码是用 Scala 编写的,但我使用的是 Java API。 Scala 可以无缝地与 Java 类.
一起工作
如果您查看 deleteFileCheckpoint 函数,我已经注释掉了一部分,我也尝试过这种方法。它具有完全相同的行为。
This is mind boggling. I can't understand why. The node is supposed to be deleted.
我不知道你为什么感到惊讶。您正在创建一个 PersistentNode
,它的存在是为了在节点被删除时自动重新创建该节点。事实上,周围的所有代码都非常令人费解。它复制了 PersistentNode
在内部所做的事情。你不需要做所有其他的事情。只需使用 PersistentNode
.
此外,像 checkExists() 这样的代码后跟基于结果的操作几乎不会在生产环境中运行。 ZooKeeper 是高并发和最终一致的。这就是为什么您应该始终使用 Curator 的食谱而不是手动编码解决方案的原因。
我正在尝试创建一个永久性 ZNode 并存储我已处理的特定文件的行数。创建就像它应该的那样工作,从节点读取数据也是如此,但是如果它在相同的代码中,删除就不起作用。我会解释我的意思。
我创建了函数:
setOrCreateFileCheckpoint(fileName: String, lineNumber: Int) :- 检查 ZNode 是否存在,如果不存在则创建它,并将存储的值设置为 行号 getFileCheckpoint(fileName: String) :- returns ZNode 中存储的值 deleteFileCheckpoint(fileName: String) :- 删除 ZNode
下面是所有三个的代码:
/*
updates or creates a checkpoint for a file being processed
*/
def setOrCreateFileCheckpoint(fileName: String, lineNumber: Int): Unit =
{
val fileCheckpointPath = checkpointPoolPath + "/" +fileName
val zk = getZookeeper
val zkCuratorClient = getZookeeperCuratorClient
if ( zk.exists(fileCheckpointPath, false) == null)
{
val node = new PersistentNode(zkCuratorClient, CreateMode.PERSISTENT, false, fileCheckpointPath, lineNumber.toString.getBytes())
node.start()
}
else
zk.setData(fileCheckpointPath, lineNumber.toString.getBytes(), -1)
}
/*
gets checkpoint for a file
*/
def getFileCheckpoint(fileName: String): Int =
{
val fileCheckpointPath = checkpointPoolPath + "/" +fileName
val zk = getZookeeper
val zkCuratorClient = getZookeeperCuratorClient
if ( zk.exists(fileCheckpointPath, false) != null)
new String(zk.getData(fileCheckpointPath, false, null)).toInt
else
0
}
/*
deletes the file checkpoint so that we don't keep accumulating zNodes on the zookeeper
*/
def deleteFileCheckpoint(fileName: String): Unit =
{
val fileCheckpointPath = checkpointPoolPath + "/" +fileName
val zk = getZookeeper
if ( zk.exists(fileCheckpointPath, false) == null)
{
throw RuntimeException("Trying to delete checkpoint that doesn't exist for file: " + fileName)
}
else
{
/*println(zk.exists(fileCheckpointPath, false).getVersion)
zk.delete(fileCheckpointPath, zk.exists(fileCheckpointPath, false).getVersion)*/
deleteChildren(zk, fileCheckpointPath, true)
}
}
以下是我正在测试并感到困惑的代码:
ZookeeperUtility.setOrCreateFileCheckpoint("file1", 2000) //let's call it cre1
println(ZookeeperUtility.getFileCheckpoint("file1")) //let's call it get1
ZookeeperUtility.deleteFileCheckpoint("file1") //let's call it del1
println("del1")
ZookeeperUtility.deleteFileCheckpoint("file1") //let's call in del2
println("del2")
运行 1:
第一步:我运行上面显示的代码
结果:del2遇到错误
第 2 步:注释掉 cre1 并再次 运行 代码
结果:获取节点,给出正确的值,因为在 del2 上遇到结果错误。这令人难以置信。我不明白为什么。该节点应该被删除。
第 3 步:cre1 仍然注释,与上一步相同,运行 代码再次
结果:节点不存在在 get1 处给出 0,这意味着节点不存在。在 del1 处遇到错误。这是在第 2 步中应该发生的事情
运行2:
第一步:注释掉del2,运行代码
结果:创建节点,获取正确数据,正常退出
第二步:注释掉cre1,运行代码
结果:从应该删除的节点中获取值 2000。正常退出
第三步:运行再次使用与第二步相同的代码
结果:获取 0,del1 时遇到错误。
如果我 运行 代码一次一步,如果我只在一个 运行 中创建,则只在下一个 运行 中获取并且只在 运行 中删除=] 之后,一切正常。我快要拔头发了。
P.S。代码是用 Scala 编写的,但我使用的是 Java API。 Scala 可以无缝地与 Java 类.
一起工作如果您查看 deleteFileCheckpoint 函数,我已经注释掉了一部分,我也尝试过这种方法。它具有完全相同的行为。
This is mind boggling. I can't understand why. The node is supposed to be deleted.
我不知道你为什么感到惊讶。您正在创建一个 PersistentNode
,它的存在是为了在节点被删除时自动重新创建该节点。事实上,周围的所有代码都非常令人费解。它复制了 PersistentNode
在内部所做的事情。你不需要做所有其他的事情。只需使用 PersistentNode
.
此外,像 checkExists() 这样的代码后跟基于结果的操作几乎不会在生产环境中运行。 ZooKeeper 是高并发和最终一致的。这就是为什么您应该始终使用 Curator 的食谱而不是手动编码解决方案的原因。