Странное поведение 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 отличается высокой степенью одновременности и, в конечном итоге, согласованностью. Вот почему вы всегда должны использовать рецепты Куратора, а не решения для ручного кодирования.

Другие вопросы по тегам