Почему «пусть решает координатор» — не решение
Координатор удобен, пока система живёт в одном процессе на одной машине. Как только участники распределены, у координатора появляются три свойства, которые в продакшене стоят дорого: он узкое место по пропускной способности, единая точка отказа и единственный, кому все обязаны верить.
Третье свойство обычно недооценивают. «Верить» здесь не про злой умысел: достаточно программной ошибки, устаревшего состояния или частичной потери связи, чтобы координатор начал раздавать решения, противоречащие тому, что видят остальные. И система это примет — потому что доверие встроено в архитектуру.
Что значит византийская модель отказов
Обычная модель отказа считает, что узел либо работает правильно, либо не работает вовсе. Византийская допускает худшее: узел работает, но ведёт себя произвольно — присылает разным участникам разные версии, повторяет старые сообщения, подписывается чужим именем, голосует дважды.
Для сети автономных агентов это не паранойя, а честная постановка. Участник может быть на чужой машине, работать на другой версии кода, страдать от рассинхронизации времени или быть скомпрометированным. Протокол должен оставаться корректным в этих условиях, а не в идеальных.
Как устроен один цикл согласия
- Лидер раунда рассылает подписанное предложение: какое изменение общего состояния он предлагает зафиксировать.
- Каждая реплика самостоятельно проверяет предложение — корректность перехода состояния, номер последовательности, подпись — и отвечает собственным подписанным голосом.
- Лидер собирает кворум уникальных голосов и рассылает сертификат фиксации.
- Каждая реплика проверяет все подписи в сертификате, надёжно записывает его в журнал и только затем применяет изменение.
Арифметика устойчивости
Для комитета из n участников допустимое число произвольно ведущих себя реплик и размер кворума считаются так:
f = floor((n - 1) / 3)
quorum = 2f + 1Практически: комитет из четырёх переживает одного отказавшего или злонамеренного участника, если остальные трое способны общаться. Из этой формулы следует и неприятная правда — устойчивость покупается участниками: чтобы пережить двоих, нужно семеро. Согласие стоит дорого, и это аргумент применять его выборочно.
Что протокол обязан отвергать
- повторное голосование одного участника — иначе кворум набирается одним активным узлом;
- голоса от тех, кто не входит в комитет;
- изменённые команды — подпись должна покрывать содержимое, а не факт отправки;
- неверный номер последовательности или раунда — защита от применения устаревших решений;
- подмену подписи и повтор ранее перехваченного сообщения.
Всё это проверяется до того, как сообщение доходит до логики согласия: транспорт подтверждает отправителя, получателя, отметку времени и одноразовый номер. Разделение ответственности здесь принципиально — код согласия не должен заниматься сетевой безопасностью, иначе ошибка в одном месте разрушает оба свойства.
Смена лидера и догоняющая синхронизация
Лидер может исчезнуть или замолчать. Тогда участники голосуют за смену раунда, и лидерство переходит дальше. Это не аварийная процедура, а штатная часть протокола: система должна продолжать работу без вмешательства человека.
Реплика, которая была недоступна, догоняет по сертификатам: запрашивает все зафиксированные решения после своего последнего номера и применяет их, проверяя подписи. Ей не нужно верить тому, кто прислал историю, — сертификаты самодостаточны.
Где это нужно агентной системе
Не везде. Согласие оправдано там, где решение общее и необратимое:
- изменение общего состояния, которое видят все участники;
- допуск нового участника в доверенный контур;
- операции с ресурсами, где двойная трата недопустима;
- структурные операции — объединение группы участников в одного и обратное разворачивание.
Всё остальное — локальные решения участников и парные договорённости, которым согласие всей группы не требуется. Попытка проводить через комитет каждое действие превращает живую систему в медленную: цена согласия платится за каждое решение, а польза появляется только там, где расхождение действительно опасно.