WAL PostgreSQL обеспечивает порядок устойчивой записи изменений перед страницами данных. Журнал Raft согласует порядок команд между участниками. Слова «журнал есть на диске» не заменяют ни условие фиксации Raft, ни проверку режима сохранности базы.
Почему это важно
При переключении важно восстановить согласованную историю, а не выбрать любой самый длинный файл журнала. Незафиксированная запись может исчезнуть, а зафиксированная — ещё ждать применения. Эти различия определяют, чему верить в ответе клиенту и в диагностике отстающего узла.
Что подтверждено
Лидер Raft принимает команду клиента, добавляет запись со своим текущим сроком в журнал и отправляет её ведомым узлам через AppendEntries. Индекс задаёт положение записи; срок указывает, при каком лидерстве она появилась.
Граница применимости: Raft, обычная репликация команд в журнале; наличие записи ещё не означает её фиксацию.
Наличие записи на одном узле не доказывает фиксацию решения. Лидер Raft может продвинуть фиксацию по числу копий до записи своего текущего срока, сохранённой большинством голосующих участников. Для записей прежнего срока одного подсчёта копий недостаточно.
Граница применимости: Правило Raft для продвижения commitIndex при фиксированном составе; большинство включает лидера и участвующих голосующих узлов, а не любые копии файла.
Лидер Raft не объявляет запись прежнего срока зафиксированной только потому, что она есть у большинства. Когда по правилу большинства фиксируется запись его текущего срока, предшествующая ей часть этого журнала также становится зафиксированной. Поэтому для старой записи важна доказанная история фиксации, а не только число копий.
Граница применимости: Raft, правило фиксации записей прежних сроков и сохранение префикса журнала; ранее доказанная фиксация не отзывается.
После смены лидера ведомый узел может заменить конфликтующий незафиксированный хвост журнала записями нового лидера. Запись могла уже лежать на диске этого узла, но так и не стать частью зафиксированной истории.
Граница применимости: Raft, устранение конфликтующих незафиксированных записей через AppendEntries; не правило произвольного удаления зафиксированных команд.
Фиксация выбирает запись как часть согласованной истории. Применение исполняет её команду в машине состояний. На отстающем узле индекс последней применённой записи может быть меньше индекса известной ему фиксации, поэтому наличие согласованной истории ещё не означает, что его рабочее состояние уже обновлено.
Граница применимости: Raft, различие commitIndex и lastApplied на одном узле.
Если два корректных журнала Raft содержат запись с одинаковыми индексом и сроком, протокол гарантирует совпадение этой записи и предшествующей части журналов. Один одинаковый индекс без срока не даёт такого основания.
Граница применимости: Свойство согласованности журналов Raft в модели протокола; не метод сравнения произвольно повреждённых файлов.
В описанном Raft лидер отвечает клиенту результатом команды после её фиксации и применения к своей машине состояний. Подтверждение ведомым получения записи — другой этап и не тождественно такому ответу клиенту.
Граница применимости: Протокол обработки команд клиента в исходной статье Raft; дополнительные гарантии внешних эффектов не заявляются.
Для линеаризуемого чтения описанный лидер Raft должен знать зафиксированный префикс, зафиксировав запись своего срока, проверить через большинство, что его не сменил другой лидер, и дождаться применения нужного префикса. Само прежнее звание лидера не разрешает читать отстающее локальное состояние после разделения.
Граница применимости: Способ линеаризуемого чтения из раздела о взаимодействии с клиентами исходной статьи Raft; иные оптимизации чтения здесь не описываются.
Не путать
Отставание нужно привязывать к этапу: запись может ещё передаваться, уже храниться или ждать применения. В Raft к этому добавляется точное правило фиксации согласованного журнала; произвольный счётчик копий его не заменяет.
Что проверить
- Разделите получение, устойчивое сохранение, фиксацию, применение и ответ клиенту.
- Проверьте текущий срок лидера вместе с индексом интересующей записи.
- Для большинства считайте только участников, имеющих право голоса в применимой конфигурации.
- Не фиксируйте старую запись по одному числу копий; проверьте правило её включения в согласованный префикс.
- При смене лидера проверьте замену конфликтующего незафиксированного хвоста.
- Сопоставьте индекс фиксации и индекс применения на узле, обслуживающем чтение.
- Для чтения бывшего лидера испытайте подтверждение его полномочий после разделения сети.
- Не выдавайте сохранённую запись ведомого за готовый результат операции клиента.
Первоисточники
In Search of an Understandable Consensus Algorithm (Extended Version)
Stanford University / USENIX · Ongaro and Ousterhout, USENIX ATC 2014 extended paper
Первичное описание Raft: leader election, replicated log, commit majority и safety.
Открыть первоисточникLinearizability: A Correctness Condition for Concurrent Objects
Carnegie Mellon University / ACM · Herlihy and Wing, ACM TOPLAS 12(3), July 1990
Даёт формальное real-time correctness condition для concurrent operations.
Открыть первоисточникPostgreSQL 18 Documentation: Write-Ahead Logging
PostgreSQL Global Development Group · PostgreSQL 18, Chapter 28.3
Определяет write-ahead rule, REDO crash recovery и роль checkpoint.
Открыть первоисточникPostgreSQL 18 Documentation: Log-Shipping Standby Servers
PostgreSQL Global Development Group · PostgreSQL 18, Chapter 26.2
Фиксирует async default, synchronous commit wait points и связь replication delay с data loss.
Открыть первоисточник