#replication #distributed-system #consensus #raft
Вопрос:
Допустим , у вас есть 3 сервера S1
, S2
и S3
. S1
(лидер), копирует журнал в S2
S3
клиент, а затем применяет ответ журнала к клиенту и завершает работу. Итак, у нас есть
S1 1
S2 1
S3 1
Теперь, когда S2
станет лидером (с голосованием от S3
), как он будет применять журнал? Согласно статье на плоту
If there exists an N such that N > commitIndex, a majority
of matchIndex[i] ≥ N, and log[N].term == currentTerm:
set commitIndex = N.
В приведенном выше случае срок S2
( commitIndex
= 0) будет равен 2, в то время как срок журнала всегда будет равен 1; следовательно, последнее условие не будет выполнено? Я что-то упускаю?
Ответ №1:
Каждый узел имеет журнал событий с двумя основными указателями: зафиксированные события и незафиксированные события. Суть протокола raft состоит в том, чтобы реплицировать оба этих указателя по всей системе.
| 0 1 2 3 | 4 5 6 7 8 9 |
^ ^
Committed Uncommitted
Каждое сообщение о репликации, которое Подписчик получает от Лидера, обновляет оба этих указателя. В сообщении есть события для добавления в журнал (обновление uncommitted
указателя). Он также имеет индекс для обновления committed
указателя.
Когда Подписчик получает это сообщение и обновляет свой committed
указатель, он применяет все события, которые только что перешли от незафиксированных к зафиксированным.
committed
Указатель, отправленный Подписчикам, является копией того, что есть в журнале Лидера. Лидер обновляет свой committed
указатель, когда получает кворум от Подписчиков, и применяет все события, которые перешли от незафиксированных к зафиксированным.
Новоизбранный Лидер сначала должен убедиться, что его версия журнала реплицируется Подписчикам, и по мере того, как новый Лидер получает кворум от Подписчиков, он обновляет свой committed
указатель, реплицирует этот указатель обратно Подписчикам и применяет события, описанные выше.
Комментарии:
1. Как описано в статье raft, мы поддерживаем lastApplied и commitIndex, но в описанном выше сценарии, когда S1 (первый лидер) умирает, он имеет состояние, подобное S1(журналы:[1], commitIndex: 1, lastApplied: 1), когда у s2 и s3 есть S2(журналы:[1], commitIndex: 0, lastApplied: 0) S3(журналы:[1], commitIndex: 0, lastApplied: 0), Поскольку лидер никогда не фиксирует журналы из более старого термина, эти журналы никогда не будут зафиксированы.
2. Неправда! Если какой-либо узел когда-либо имеет значение журнала как зафиксированное, то в конечном итоге все остальные узлы будут видеть это значение как зафиксированное. Это само определение зафиксированных в консенсусных алгоритмах.
3. Запись в журнале фиксируется после того, как руководитель, создавший запись, реплицировал ее на большинстве серверов. Следовательно, как только он реплицируется, лидер фиксирует его. Я думаю, что недостающая часть, о которой говорится в статье в разделе 8, Свойство Полноты лидера гарантирует, что у лидера есть все зафиксированные записи, но в начале своего срока он может не знать, какие это. Чтобы выяснить это, ему нужно зафиксировать запись из своего срока. Плот справляется с этим, заставляя каждого лидера вносить пустую запись об отказе от операции в журнал в начале своего срока.