К основному содержимому
к выпуску
Конспект выпуска2023Fellow

Distributed Systems — выпуск 8

Восьмую главу — про отказоустойчивость — клуб читает без Александра: он заболел, и главу разбирают двое приглашённых коллег из Тинькофф. Денис Костоусов, Scala-разработчик из Перми, берёт на себя группы процессов и консенсус; Салих, ведущий SRE-инженер из Казани, — определения, сеть и восстановление. Разговор занял час сорок.

Code of Architecture · книжный клуб7 минут

Конспект сокращён относительно полного выпуска; примеры и оценки передают опыт и позиции участников.

Основная линия материала
01

Надёжность, сбои и модели отказов

Ведущий открывает выпуск с плохой новости: Александр заболел, ему желают выздоровления и ждут к следующей главе. Денис начинал системным администратором, через Java добрался до Scala и пишет на ней последние пять лет; Салих работает в управлении открытия новых продуктов, куда падают заявки банка со всех фронтов, банкоматов и пост-терминалов, — «жизнь клиента начинается с нас». В самом начале у него отваливается микрофон, и, вернувшись, он шутит: произошла ошибка и со временем сама восстановилась. Надёжность книга раскладывает на четыре свойства: доступность — готовность прямо сейчас, надёжность — работа без сбоя на длинном интервале, безопасность — отказ, не приводящий к катастрофе (пример с атомной станцией), ремонтопригодность — возможность вести работы, не теряя доступности. Доступность и надёжность не совпадают: одна двухнедельная остановка за год даёт 96% доступности. Участники признаются, что английское dependability на русский аккуратно не ложится: разные слова схлопываются в одно «надёжный».

Отказы для авторов — нормальное состояние системы, а среднее время до отказа и до ремонта считается лишь там, где понятно, что считать отказом. Формулировку «ошибка — это часть системы, которая может привести к сбою» участники находят чуть ли не в каждой главе. Сбои делят на скоротечные (магнитный импульс на линии — повторная отправка уже проходит), прерывистые — самые трудные в диагностике, потому что SRE приходит, а следов не осталось, — и постоянные, вроде вылетевшей планки памяти. Crash-отказ иллюстрируют кнопкой reset: она жила на задней стенке системного блока, потом переехала вперёд, и автор надеется, что когда-нибудь уедет обратно. В omission-отказе запрос отбрасывают, потому что треда-обработчика просто нет; тайминговый бывает и обратным — клиента накачивают данными слишком рано, и видеостриминг падает. Худший класс — произвольные, они же византийские: процесс не падает, а врёт, отдавая false вместо true. Имя взято из империи, славной интригами и ложными утверждениями, а начиналось всё, по словам участника, с албанских армий, которые потом переименовали, чтобы никого не задеть.

02

Группы процессов и цена консенсуса

Резервирование сводится к избыточности трёх видов: информационной (код Хэмминга, добавляющий биты для восстановления сообщения), временной (ретраи и переотправки) и физической — необязательно железной, это может быть и группа инстансов приложения; образцом приводят тройное модульное резервирование из электротехники, где три избирателя выбирают то, что показало большинство сигналов. Процессы объединяют в группы, которые снаружи выглядят единым целым: у плоской нет единой точки отказа, но внутренняя коммуникация сложна; иерархическая дешевле по числу стрелок на диаграмме, зато её ахиллесова пята — координатор, и когда он падает, начинается «самая весёлая часть балета». Отдельная задача — членство: либо координатор состава, который сам упадёт, либо все знают про всех и вступление превращается в долгую процедуру. Вывод главы участники формулируют как «халявы не бывает»: от простого падения спасает k+1 узел, а от произвольных отказов книга требует 3k+1 — семь серверов, чтобы пережить аварию на двух, и это «звучит страшно».

Консенсус рассылкой всех всем — «простой, понятный, очевидный и неправильный», консенсус в детской песочнице. Практический пример — Raft, и участника удивило, что его дают раньше Paxos: тот исторически первый, но сложный и мало используемый. В Raft каждый сервер ведёт лог команд, лидером становится узел с самым актуальным логом, а ведомый полностью ретранслирует запрос лидеру — «думаешь, что долбишься не в координатора, а запросы всё равно летят к нему». Хранилище секретов HashiCorp Vault недавно получило собственный Raft, а раньше требовало внешней системы вроде ZooKeeper или Consul, который и сам построен на Raft; в Kafka, по давним воспоминаниям другого участника, тоже планировали уйти от внешнего ZooKeeper к своей реализации. Paxos же, по словам участника, — остров где-то в Адриатике, в районе Греции, и алгоритм, описанный как заседания условно демократического органа: непонимание породило толкователей, к которым лет через восемь присоединился и сам автор со второй работой, а реализации ни разу не повторили идеал. Ограничений два: огромная стоимость и теорема CAP, из которой выбирают любые два свойства.

03

Коммит, восстановление и реальный мир

Каналы связи подвержены тем же классам ошибок, и задача — их замаскировать. TCP закрывает переотправку, но разрыв клиент видит явно и обычно переустанавливает соединение на уровне приложения; RPC пытается спрятать сеть целиком и всё равно заставляет обрабатывать сетевые исключения. Повтор требует, чтобы сервер различал дубли: идемпотентные вызовы, нумерация сообщений на клиенте, флажок повтора — а из семантик доставки участник отдельно отмечает четвёртую, не гарантирующую ничего. Для группы книга разделяет получение и доставку, экономит трафик негативными подтверждениями и выстраивает порядок от никакого через FIFO и причинно-следственный на векторных часах до тотального — самого жёсткого. Двухфазный коммит ломается, когда координатор падает в состоянии ожидания, не успев разослать решение: узлы вынуждены ждать его возвращения. Трёхфазный добавляет фазу pre-commit, по которой участники решают судьбу транзакции сами.

Восстановление бывает прямым и обратным. Прямое требует заранее знать все ошибки, поэтому почти не встречается; обратное ничего не знает о процессе, просто снимает чекпоинты — и применимо везде. Но и удачный откат чинит не всё: если банкоматы уже выдали деньги, система вернётся в прошлое, а деньги нет. Координированный чекпоинт снимают протоколом двухфазной фиксации, независимый дешевле, но грозит каскадным откатом хоть до нуля; между чекпоинтами ведут журнал сообщений, а пессимистичное журналирование запрещает отвечать, пока приём не зафиксирован. Отсюда возражение Дениса: книга всё время предлагает повторить команду, а в реальном мире деньги второй раз не отправишь. В его практике платёж уходил, тайм-аут срабатывал через минуту, система рапортовала о неуспехе, а клиенту приходила SMS о списании — и разбирать это приходилось вне системы, по реестру, руками. По ходу разговора участники сравнивают издания: в третьем Raft уже был, а блокчейн добавили почти во все главы.

Выводы

Что стоит унести с собой

  1. 01Надёжность в главе — четыре разных свойства: доступная система может быть ненадёжной и наоборот, а одна двухнедельная остановка за год даёт 96% доступности.
  2. 02Отказы различают по причине (скоротечные, прерывистые, постоянные) и по модели — crash, omission, тайминг, неверный ответ и произвольные, самые дорогие в защите.
  3. 03Цена надёжности растёт нелинейно: k+1 узел спасает от падения, а от произвольных отказов книга требует 3k+1 — семь серверов, чтобы пережить аварию на двух.
  4. 04Восстановление почти всегда обратное — чекпоинты плюс журнал сообщений; но откат не вернёт выданные банкоматом деньги, и такие конфликты решают вне системы.

Источники