Странное поведение ZNode в Java Zookeeper API. Невозможно правильно удалить ZNode. Это дает неожиданные результаты
Я пытаюсь создать постоянный ZNode и сохранить количество строк определенного файла, который я обработал. Создание работает точно так же, как и чтение данных с узла, но удаление не работает, если оно находится в том же коде. Я бы объяснил, о чем я.
Я создал функции:
setOrCreateFileCheckpoint (fileName: String, lineNumber: Int):- проверяет, существует ли ZNode, создает его, если нет, и устанавливает сохраненное значение в lineNumbergetFileCheckpoint(fileName: String):- возвращает значение, хранящееся в ZNodedeleteFileCheckpoint(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:
Шаг 1. Я запускаю код, показанный выше
Результат: ошибка на del2
Шаг 2: закомментируйте cre1 и снова запустите код
Результат: узел получен, выдает правильное значение, поскольку ошибка результата обнаружена на del2. Это ошеломляет. Не понимаю почему. Предполагается, что узел будет удален.
Шаг 3: оставив комментарий cre1, как и на предыдущем шаге, снова запустите код
Результат: узел не существует дает 0 в get1, что означает, что узел не существует. ошибка обнаружена в del1. Что должно было произойти на шаге 2
Run2:
Шаг 1: закомментируйте del2, запустите код
Результат: создает узел, извлекает правильные данные, нормально закрывается
Шаг 2: закомментируйте cre1, запустите код
Результат: получает значение 2000 из узла, который предполагалось удалить. выходит нормально
Шаг 3: снова выполните тот же код, что и на шаге 2.
Результат: получает 0, ошибка обнаружена на del1.
Если я запускаю код по одному шагу за раз, если я создаю только за один прогон, извлекаю только в следующем прогоне и удаляю только в прогоне после этого, все работает так, как должно. Я на грани выдергивания волос.
PS Код написан на Scala, но я использую Java API. Scala может казаться бессмысленной работой с Java-классами.
Если вы посмотрите на функцию deleteFileCheckpoint, которую я закомментировал, я тоже пробовал этот подход. У него точно такое же поведение.
1 ответ
Это ошеломляет. Не понимаю почему. Предполагается, что узел будет удален.
Не знаю, почему ты удивлен. Вы создаетеPersistentNode
который существует для автоматического воссоздания узла в случае его удаления. Фактически, весь окружающий код очень загадочен. Это дублирует то, чтоPersistentNode
делает внутренне. Вам не нужно делать все остальное. Просто используйтеPersistentNode
.
Кроме того, такой код, как checkExists(), за которым следует действие, основанное на результате, почти никогда не будет работать в производственной среде. ZooKeeper отличается высокой степенью одновременности и, в конечном итоге, согласованностью. Вот почему вы всегда должны использовать рецепты Куратора, а не решения для ручного кодирования.