При чтении ZooKeeper рецепта блокировки я смутился. Похоже, что этот рецепт для распределенных шлюзов не может гарантировать «любой моментальный снимок, когда два клиента не считают, что они имеют один и тот же замок» . Но так как ZooKeeper настолько широко принят, если в справочной документации были ошибки, кто-то должен был это указать давно, так что я понял неправильно?
Задание рецепта для распределенных блокировок :
Блокировка р>
Полностью распределенные блокировки, которые глобально синхронны, значение при любом моментальном снимке, когда два клиента не считают, что они имеют ту же блокировку . Они могут быть реализованы с помощью ZooKeeeper. Как и в случае очередей приоритетов, сначала определите узел блокировки.
- Вызовите create () с именем пути locknode / guid-lock- "и установите последовательность и эфемерные флаги.
- Вызовите getChildren () на узле блокировки без установки флага часов (это важно, чтобы избежать эффекта стада).
- Если путь, созданный на шаге 1, имеет суффикс с наименьшим порядковым номером, клиент имеет блокировку, и клиент выходит из протокола.
- Клиент вызывает exists () с флагом часов, установленным на пути в каталоге блокировки со следующим нижним порядковым номером.
- if exists () возвращает false, перейдите к шагу 2. В противном случае дождитесь уведомления для имени пути с предыдущего шага, прежде чем перейти к шагу 2.
Рассмотрим следующий случай:
- Клиент1 успешно приобрел блокировку (на шаге 3), с узлом ZooKeeper «locknode / guid-lock-0»;
- Клиент2 создал узел «locknode / guid-lock-1», не смог получить блокировку и теперь смотрит «locknode / guid-lock-0»;
- Позже, по какой-либо причине (скажем, перегрузке сети), Client1 не может отправить сообщение о сердцебиении в кластер ZooKeeper вовремя, но Client1 все еще работает, ошибочно полагая, что он все еще удерживает блокировку.
-
Но ZooKeeper может подумать, что сеанс Client1 отключен, а затем
- удалить "locknode / guid-lock-0",
- отправить уведомление клиенту2 (или, может быть, сначала отправить уведомление?),
- , но не может своевременно отправить уведомление «Тайм-аут сеанса» клиенту1 (скажем, из-за перегрузки сети).
- Клиент2 получает уведомление, переходит к шагу 2, получает единственный узел «locknode / guid-lock-1», который он создал сам, поэтому Client2 предполагает, что он удерживает блокировку.
- Но в то же время Client1 предполагает, что он удерживает блокировку.
Является ли это допустимым сценарием?