Подтвердить что ты не робот

Озабоченность по поводу рецепта замка

При чтении ZooKeeper рецепта блокировки я смутился. Похоже, что этот рецепт для распределенных шлюзов не может гарантировать "любой моментальный снимок, когда два клиента не считают, что они имеют один и тот же замок" . Но так как ZooKeeper настолько широко принят, если в справочной документации были ошибки, кто-то должен был это указать давно, так что я понял неправильно?

Цитата рецепт для распределенных блокировок:

Блокировка

Полностью распределенные блокировки, которые глобально синхронны, значение при любом моментальном снимке, когда два клиента не считают, что они имеют ту же блокировку. Они могут быть реализованы с помощью ZooKeeeper. Как и в случае очередей приоритетов, сначала определите блокировку node.

  • Вызовите create() с именем пути "locknode/guid-lock-" и установите последовательность и эфемерные флаги.
  • Вызовите getChildren() на блокировке node без установки флага часов (это важно, чтобы избежать эффекта стада).
  • Если путь, созданный на шаге 1, имеет суффикс с наименьшим порядковым номером, клиент имеет блокировку, и клиент выходит из протокола.
  • Клиент вызывает exists() с флагом часов, установленным на пути в каталоге блокировки со следующим нижним порядковым номером.
  • if exists() возвращает false, перейдите к шагу 2. В противном случае дождитесь уведомления для имени пути с предыдущего шага, прежде чем перейти к шагу 2.

Рассмотрим следующий случай:

  • Клиент1 успешно приобрел блокировку (на шаге 3), с ZooKeeper node "locknode/guid-lock-0" ;
  • Клиент2 создал node "locknode/guid-lock-1", не смог получить блокировку и теперь смотрит "locknode/guid-lock-0" ;
  • Позже, по какой-либо причине (скажем, перегрузке сети), Client1 не может отправить сообщение о сердцебиении в кластер ZooKeeper вовремя, но Client1 все еще работает, ошибочно полагая, что он все еще удерживает блокировку.
  • Но ZooKeeper может подумать, что сеанс Client1 отключен, а затем

    • удалить "locknode/guid-lock-0" ,
    • отправить уведомление клиенту2 (или, может быть, сначала отправить уведомление?),
    • но не может своевременно отправить уведомление "Тайм-аут сеанса" клиенту1 (скажем, из-за перегрузки сети).
  • Клиент2 получает уведомление, переходит к шагу 2, получает единственный node "locknode/guid-lock-1", который он создал сам, поэтому Client2 предполагает, что он удерживает блокировку.
  • Но в то же время Client1 предполагает, что он удерживает блокировку.

Является ли это допустимым сценарием?

4b9b3361

Ответ 1

Сценарий, который вы описали, может возникнуть. Клиент 1 считает, что у него есть блокировка, но на самом деле его сеанс завершен, и клиент 2 получает блокировку.

Клиентская библиотека ZooKeeper сообщит клиенту 1, что его соединение отключено (но клиент не знает, что срок действия сеанса истек, пока клиент не подключится к серверу), поэтому клиент может написать код и предположить, что его блокировка был потерян, если он был слишком долго отключен. Но поток, который использует блокировку, должен периодически проверять, что блокировка по-прежнему действительна, что по своей природе является безупречным.

Ответ 2

... Но, Zookeeper может подумать, что сеанс client1 отключен, а затем...

Из документации Zookeeper:

  • Удаление node приведет к тому, что один клиент проснется с тех пор каждый node просматривается ровно одним клиентом. Таким образом, вы избегаете стадо.
  • Нет опроса или тайм-аутов.

Итак, я не думаю, что проблема, которую вы описываете, возникает. Мне кажется, что существует риск зависания блокировок, если что-то происходит с клиентами, которые их создают, но сценарий, который вы описываете, не должен возникать.