Читай реальную математику доступности, конфиг и код, затем делай арифметику: расчёт бюджета ошибок, сложение последовательной доступности, проверку размера резервирования и retry-конфиг, что превращает медленную зависимость в сбой.
SDSenior◷ 14 min
Уровень
ОсновыJuniorMiddleSenior
Инциденты доступности живут в числах, не в прозе: бюджет SLO, цепочка зависимостей, перемноженная вместе, пул, размеренный до N вместо N+1, retry-политика без backoff. Читай каждый сниппет, делай арифметику в голове и выбирай ответ, под которым подписался бы senior-дежурный.
Практикуй петлю, что гоняешь во время ревью доступности или инцидента: локализуй числа, примени математику девяток/бюджета ошибок/сложения или правила ретраев-и-таймаутов и выбери изменение, что арифметика реально поддерживает, — а не то, что звучит успокаивающе.
Что вернёт error_budget_minutes(0.999) за окно в 28 дней и что это значит?
Heads-up ~4,3 мин это ЧЕТЫРЕ девятки (99,99%) за ~30 дней. Три девятки (99,9%) за 28 дней это 0,001 × 28 × 24 × 60 ≈ 40,3 мин. Следи, какую девятку считаешь.
Heads-up Это две девятки (99%, то есть 0,01). SLO 99,9% использует 0,001, давая ≈40,3 мин за 28 дней, не 403. Ты ошибся в десять раз — на целую девятку.
Heads-up 99,9% явно разрешает 0,1% отказывать. Бюджет — 0,001 × 28 × 24 × 60 ≈ 40,3 мин — тратимый бюджет ошибок, не ноль. Трактовка как ноль выбрасывает весь смысл SLO.
Сниппет 2 — цепочка зависимостей
# запрос должен пройти все четыре, чтобы успетьchain = {"lb": 0.999, "app": 0.999, "cache": 0.999, "db": 0.999}avail = 1.0for a in chain.values(): avail *= aprint(round(avail, 4)) # что напечатает и это >= SLO 99,9%?
Викторина
Completed
Что это напечатает и держит ли путь SLO 99,9%?
Heads-up Последовательная доступность умножается, а не копирует значение одного звена. 0,999⁴ ≈ 99,6%, ниже SLO 99,9%. Каждая добавленная зависимость снижает доступность пути.
Heads-up Добавление последовательных компонентов СНИЖАЕТ доступность, а не повышает. Произведение — 0,999⁴ ≈ 99,6%, не 99,96%. Нельзя выйти на четыре девятки из четырёх звеньев по три девятки последовательно.
Heads-up Для последовательного пути произведение не зависит от порядка: 0,999⁴ ≈ 99,6% при любой последовательности. Суть в том, что оно ниже SLO, так что цепочке нужно резервирование или меньше хопов.
Сниппет 3 — конфиг резервирования
# конфиг автоскейлера / ёмкостиpeak_required_instances: 6 # инстансов нужно нести пикdesired_instances: 6 # сколько реально гоняем# заметка: "мы гоняем несколько инстансов, значит слой зарезервирован"
Викторина
Completed
Команда зовёт слой зарезервированным, ведь гоняет несколько инстансов. По уроку резервирования, что не так и какова починка?
Heads-up Резервирование значит пережить потерю при сохранении ПИКА, для чего нужен запасной. При desired = peak = 6 потеря одного оставляет 5 на пик из 6: под ёмкостью. Это N, а не N+1.
Heads-up Это хуже — теперь ты под пиком даже при нуле отказов. Резервирование ИМЕННО про запас ёмкости, размеренный под пик: нужен N+1 = 7, а не меньше пика.
Heads-up Второй балансировщик убирает другой SPOF (балансировщик), но не чинит резервирование инстансов: 6 инстансов на пик из 6 — всё ещё N. Нужен 7-й инстанс для N+1 в этом слое.
Сниппет 4 — retry-политика
# клиент, зовущий нижестоящий сервисRETRY_CONFIG = { "max_attempts": 5, "timeout_seconds": 30, # на попытку "backoff": "none", # ретрай немедленно "jitter": False,}# нижестоящий сервис только что начал отдавать медленные ответы
Викторина
Completed
Нижестоящий сервис замедляется. Что эта retry-политика с ним делает и какова верная конфигурация?
Heads-up При перегрузке долбёж 5× немедленно умножает нагрузку ровно тогда, когда зависимость меньше всего может это вынести (retry storm). Надёжность даёт ограниченный, с backoff, с jitter ретрай, а не более упорный.
Heads-up У перегруженной зависимости нет запаса ёмкости; ретраи — добавленная нагрузка на отказывающую систему, ускоряющая коллапс. Поэтому нужен бюджет ретраев плюс backoff и jitter.
Heads-up Меньше попыток помогает чуть-чуть, но таймаут 30 с (исчерпание потоков) и ретраи без backoff/без jitter в унисон — бо́льшие проблемы. Чини таймауты, добавь экспоненциальный backoff С jitter и бюджет ретраев.
Вспомните перед уходом
01
Как посчитать бюджет ошибок из SLO и какова частая ошибка на одну девятку?
02
Почему путь из четырёх звеньев по 99,9% промахивается мимо SLO 99,9% и каковы починки?
03
Что превращает медленный нижестоящий в сбой в retry-конфиге и какова безопасная конфигурация?
Итог
Каждое решение доступности в этом разделе сводится к арифметике, что читается прямо с конфига. Бюджет ошибок — это (1 − SLO) × окно — 99,9% за 28 дней ≈ 40 минут — и классический баг — промах на одну девятку (0,01 против 0,001, ошибка в 10×). Доступность пути — это произведение его последовательных звеньев, так что цепочка из четырёх звеньев по 99,9% — лишь ~99,6% и промахивается мимо SLO 99,9%; чинишь убиранием хопов или добавлением резервирования, а не правкой прозы. Резервирование — это N+1, так что desired_instances == peak_required — это N — не зарезервировано — и потеря одного в пик кренит в коллапс очередей; ты провижинишь запасной. А retry-политика с длинными таймаутами и немедленными, без jitter ретраями превращает медленную зависимость в retry storm и сбой — починка это короткие ограниченные таймауты, бюджет ретраев, экспоненциальный backoff с jitter, circuit breakers и ретраи лишь идемпотентного. Senior-привычка та же, что в разделе масштабируемости: найди числа, сделай математику и выбери починку, что поддерживает арифметика, а не ту, что звучит безопасно.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.