Команды репликации
Каждое изменение состояния блокировки реплицируется одной из команд ниже как запись лога в AppendEntries и применяется всеми узлами в одном порядке после commit большинством.
Команды (предлагает лидер)
| Команда | Поля | Значение |
|---|---|---|
Grant | key, lease_ms | захват ключа. Токена в команде нет — он назначается детерминированно машиной состояний каждого узла в момент применения, поэтому все узлы вычисляют один и тот же токен |
Release | key | освобождение ключа |
Expire | key, token | истечение lease по инициативе лидера. Удаление происходит только при совпадении token — запоздавшее или дублирующее истечение не может стереть блокировку, выданную заново в промежутке (идемпотентность) |
Результаты применения (машина состояний → лидер)
| Результат | Значение |
|---|---|
Granted { token } | захват успешен — выданный fencing-токен |
GrantRejected | Grant пришёл для уже удерживаемого ключа (защитный случай — в штатном потоке не возникает) |
Released | освобождено |
NotFound | освобождаемого ключа не было |
Expired { existed } | истечение обработано — existed показывает, было ли реальное удаление |
Noop | ничего не произошло |
Оставшееся время lease каждый узел отслеживает по своим локальным часам, но реальное удаление всегда происходит только через зафиксированную команду Expire — именно поэтому разница часов между узлами не может расколоть состояние блокировок. Если блокировка исчезла до того, как клиент получил ответ (обрыв соединения), лидер сам сразу же после выдачи предлагает Release, немедленно убирая «блокировку-призрак».
Поток — репликация Expire (истечение)
Даже истечение — это команда, проходящая через предложение лидера → commit большинством. Благодаря условию по token, даже если тот же ключ был выдан заново, пока commit задерживался, запоздало применённый Expire не сможет стереть новую блокировку.
Термины
- Машина состояний (state machine) — часть системы, которая, применяя зафиксированные команды по порядку, формирует текущее состояние (здесь — таблицу блокировок). Поскольку все узлы применяют одни и те же команды в одном и том же порядке, они всегда приходят к одному состоянию.
- Commit — состояние «подтверждено», когда команду записало большинство узлов. В машину состояний применяются только зафиксированные команды.
- Идемпотентность — свойство, при котором повторное применение одной и той же команды по ошибке не меняет результат.