Надёжность, сбои и модели отказов
Ведущий открывает выпуск с плохой новости: Александр заболел, ему желают выздоровления и ждут к следующей главе. Денис начинал системным администратором, через Java добрался до Scala и пишет на ней последние пять лет; Салих работает в управлении открытия новых продуктов, куда падают заявки банка со всех фронтов, банкоматов и пост-терминалов, — «жизнь клиента начинается с нас». В самом начале у него отваливается микрофон, и, вернувшись, он шутит: произошла ошибка и со временем сама восстановилась. Надёжность книга раскладывает на четыре свойства: доступность — готовность прямо сейчас, надёжность — работа без сбоя на длинном интервале, безопасность — отказ, не приводящий к катастрофе (пример с атомной станцией), ремонтопригодность — возможность вести работы, не теряя доступности. Доступность и надёжность не совпадают: одна двухнедельная остановка за год даёт 96% доступности. Участники признаются, что английское dependability на русский аккуратно не ложится: разные слова схлопываются в одно «надёжный».
Отказы для авторов — нормальное состояние системы, а среднее время до отказа и до ремонта считается лишь там, где понятно, что считать отказом. Формулировку «ошибка — это часть системы, которая может привести к сбою» участники находят чуть ли не в каждой главе. Сбои делят на скоротечные (магнитный импульс на линии — повторная отправка уже проходит), прерывистые — самые трудные в диагностике, потому что SRE приходит, а следов не осталось, — и постоянные, вроде вылетевшей планки памяти. Crash-отказ иллюстрируют кнопкой reset: она жила на задней стенке системного блока, потом переехала вперёд, и автор надеется, что когда-нибудь уедет обратно. В omission-отказе запрос отбрасывают, потому что треда-обработчика просто нет; тайминговый бывает и обратным — клиента накачивают данными слишком рано, и видеостриминг падает. Худший класс — произвольные, они же византийские: процесс не падает, а врёт, отдавая false вместо true. Имя взято из империи, славной интригами и ложными утверждениями, а начиналось всё, по словам участника, с албанских армий, которые потом переименовали, чтобы никого не задеть.
Группы процессов и цена консенсуса
Резервирование сводится к избыточности трёх видов: информационной (код Хэмминга, добавляющий биты для восстановления сообщения), временной (ретраи и переотправки) и физической — необязательно железной, это может быть и группа инстансов приложения; образцом приводят тройное модульное резервирование из электротехники, где три избирателя выбирают то, что показало большинство сигналов. Процессы объединяют в группы, которые снаружи выглядят единым целым: у плоской нет единой точки отказа, но внутренняя коммуникация сложна; иерархическая дешевле по числу стрелок на диаграмме, зато её ахиллесова пята — координатор, и когда он падает, начинается «самая весёлая часть балета». Отдельная задача — членство: либо координатор состава, который сам упадёт, либо все знают про всех и вступление превращается в долгую процедуру. Вывод главы участники формулируют как «халявы не бывает»: от простого падения спасает k+1 узел, а от произвольных отказов книга требует 3k+1 — семь серверов, чтобы пережить аварию на двух, и это «звучит страшно».
Консенсус рассылкой всех всем — «простой, понятный, очевидный и неправильный», консенсус в детской песочнице. Практический пример — Raft, и участника удивило, что его дают раньше Paxos: тот исторически первый, но сложный и мало используемый. В Raft каждый сервер ведёт лог команд, лидером становится узел с самым актуальным логом, а ведомый полностью ретранслирует запрос лидеру — «думаешь, что долбишься не в координатора, а запросы всё равно летят к нему». Хранилище секретов HashiCorp Vault недавно получило собственный Raft, а раньше требовало внешней системы вроде ZooKeeper или Consul, который и сам построен на Raft; в Kafka, по давним воспоминаниям другого участника, тоже планировали уйти от внешнего ZooKeeper к своей реализации. Paxos же, по словам участника, — остров где-то в Адриатике, в районе Греции, и алгоритм, описанный как заседания условно демократического органа: непонимание породило толкователей, к которым лет через восемь присоединился и сам автор со второй работой, а реализации ни разу не повторили идеал. Ограничений два: огромная стоимость и теорема CAP, из которой выбирают любые два свойства.
Коммит, восстановление и реальный мир
Каналы связи подвержены тем же классам ошибок, и задача — их замаскировать. TCP закрывает переотправку, но разрыв клиент видит явно и обычно переустанавливает соединение на уровне приложения; RPC пытается спрятать сеть целиком и всё равно заставляет обрабатывать сетевые исключения. Повтор требует, чтобы сервер различал дубли: идемпотентные вызовы, нумерация сообщений на клиенте, флажок повтора — а из семантик доставки участник отдельно отмечает четвёртую, не гарантирующую ничего. Для группы книга разделяет получение и доставку, экономит трафик негативными подтверждениями и выстраивает порядок от никакого через FIFO и причинно-следственный на векторных часах до тотального — самого жёсткого. Двухфазный коммит ломается, когда координатор падает в состоянии ожидания, не успев разослать решение: узлы вынуждены ждать его возвращения. Трёхфазный добавляет фазу pre-commit, по которой участники решают судьбу транзакции сами.
Восстановление бывает прямым и обратным. Прямое требует заранее знать все ошибки, поэтому почти не встречается; обратное ничего не знает о процессе, просто снимает чекпоинты — и применимо везде. Но и удачный откат чинит не всё: если банкоматы уже выдали деньги, система вернётся в прошлое, а деньги нет. Координированный чекпоинт снимают протоколом двухфазной фиксации, независимый дешевле, но грозит каскадным откатом хоть до нуля; между чекпоинтами ведут журнал сообщений, а пессимистичное журналирование запрещает отвечать, пока приём не зафиксирован. Отсюда возражение Дениса: книга всё время предлагает повторить команду, а в реальном мире деньги второй раз не отправишь. В его практике платёж уходил, тайм-аут срабатывал через минуту, система рапортовала о неуспехе, а клиенту приходила SMS о списании — и разбирать это приходилось вне системы, по реестру, руками. По ходу разговора участники сравнивают издания: в третьем Raft уже был, а блокчейн добавили почти во все главы.
Что стоит унести с собой
- 01Надёжность в главе — четыре разных свойства: доступная система может быть ненадёжной и наоборот, а одна двухнедельная остановка за год даёт 96% доступности.
- 02Отказы различают по причине (скоротечные, прерывистые, постоянные) и по модели — crash, omission, тайминг, неверный ответ и произвольные, самые дорогие в защите.
- 03Цена надёжности растёт нелинейно: k+1 узел спасает от падения, а от произвольных отказов книга требует 3k+1 — семь серверов, чтобы пережить аварию на двух.
- 04Восстановление почти всегда обратное — чекпоинты плюс журнал сообщений; но откат не вернёт выданные банкоматом деньги, и такие конфликты решают вне системы.