Про надёжность обычно думают в терминах «как не упасть» — репликация, failover, circuit breaker. Но есть вторая половина, о которой вспоминают в худший момент: как восстановиться, когда всё-таки упало насмерть — потеряли регион, дропнули таблицу, зашифровал вымогатель. Disaster Recovery — это дисциплина ответов на такие сценарии заранее: сколько времени на восстановление приемлемо (RTO), сколько данных можно потерять (RPO), откуда восстанавливать и — самое забываемое — проверяли ли вы, что восстановление вообще работает. Эта статья про то, как не обнаружить, что «бэкапы есть», ровно в момент, когда из них ничего не поднимается.
Пятая статья серии «System design: resilience». Главный тезис проверен на стенде architecture/resilience/dr: там катастрофа и восстановление проигрываются целиком, а фактическое время восстановления и достигнутая точка не декларируются, а замеряются — их и сравнивают с целевыми RTO/RPO.
В статье
- HA — это не DR — разные задачи, разные механизмы
- RTO и RPO — язык договорённостей о потерях
- Стратегия бэкапов — 3-2-1, полные и инкрементальные, PITR
- Restore-тест — почему бэкап без него не бэкап, с замером
- Сценарии катастроф — от DROP до вымогателя
- Мульти-регион — active-passive против active-active
- Runbook и учения — кто нажимает кнопку
- Checklist
HA — это не DR
Первое, что путают: высокая доступность и восстановление после катастрофы решают разные задачи.
- HA (high availability) — пережить отказ узла без простоя: реплики, автоматический failover, кворум. Работает, пока отказ «штатный» — умерла машина, пропала зона.
- DR (disaster recovery) — восстановиться после события, которое HA не покрывает: потеря региона целиком, логическая порча, шифровальщик.
Ключевая мысль: репликация не спасает от логической ошибки. DROP TABLE доедет до всех реплик за миллисекунды — синхронно и надёжно. Шифровальщик, прошедший по данным, тоже отреплицируется. Реплика защищает от отказа железа, а не от неверной команды: против неё нужен снимок прошлого, то есть бэкап и возможность вернуться в точку до события.
Механику HA в Postgres разбирает отдельная статья про Patroni и репликациюготовится, с 29 сентября; здесь речь о второй половине.
RTO и RPO
Две величины, которые превращают разговор о надёжности из эмоций в договорённость:
- RTO (Recovery Time Objective) — целевое время восстановления: за сколько мы обязаны снова работать.
- RPO (Recovery Point Objective) — целевая точка во времени, до которой данные обязаны быть восстановлены. Отсюда и практическое следствие: потеря — это всё, что записано после этой точки.
Оба — цели (objectives), которые назначает бизнес, а не результаты измерения. Замер даёт другое: фактическое время восстановления (его сравнивают с целевым RTO) и фактически достигнутую точку восстановления вместе с объёмом потерянных данных (сравнивают с целевым RPO). Путать цель с фактом — обычная небрежность, из-за которой «у нас RPO ноль» звучит как достижение, хотя это лишь результат одного удачного прогона.
Обе назначаются бизнесом, а не инженерами: это не «сколько получится», а «сколько приемлемо». Инженерное дело — сказать, что стоит каждый вариант. Цена растёт нелинейно: RPO в сутки — это ночной бэкап; RPO в минуты — непрерывное архивирование журнала; RPO около нуля — синхронная репликация в другой регион, за которую платят латентностью каждой транзакции.
Полезная проверка: назовите текущие RTO и RPO числом. Если ответа нет — их и не существует, есть только надежда.
Стратегия бэкапов
Классическое правило 3-2-1: три копии данных, на двух разных носителях, одна — вне площадки. К нему в наше время добавляют «одна копия неизменяемая» — против шифровальщика, который целенаправленно ищет и портит бэкапы.
Типы копий:
- Полный бэкап — снимок целиком. Прост в восстановлении, дорог по объёму и времени.
- Инкрементальный/дифференциальный — только изменения; дешевле, но восстановление требует цепочки, и разрыв в ней стоит дорого.
- PITR (point-in-time recovery) — полный бэкап плюс непрерывный журнал (WAL в Postgres). Позволяет восстановиться не «на момент бэкапа», а на любую точку между ним и катастрофой.
Именно PITR сдвигает достижимую точку восстановления: без него она — момент последнего бэкапа, с ним — почти момент катастрофы (теряется лишь то, что не успело доехать в архив). Это и позволяет выполнять целевой RPO, измеряемый минутами, а не сутками. Как устроен сам журнал — в статье про WAL; общие принципы хранения копий — в бэкапах для ценных данных.
Restore-тест
Здесь главная мысль статьи: бэкап, из которого ни разу не восстанавливали, — не бэкап, а предположение. Он может быть пустым, битым, неполным (забыли роль/расширение), зашифрованным ключом, который лежит только на упавшем сервере. Узнать это в момент катастрофы — худший из вариантов.
Дисциплина простая: восстановление гоняется регулярно и автоматически, в изолированную среду, с проверкой данных и замером времени. Тогда вы знаете фактическое время восстановления и можете честно сказать, укладываетесь ли в целевой RTO, — вместо того чтобы надеяться.
Стенд делает ровно это. Сценарий: 100 заказов, полный бэкап, ещё 50 заказов (живут только в журнале), затем катастрофа — DROP TABLE. Восстановление на точку перед катастрофой:
✅ таблица поднята, DROP отменён, все 150 заказов на месте, инстанс промоутнут
фактическое время восстановления: 7.3 с ← сравнивать с целевым RTO
достигнутая точка восстановления: момент перед катастрофой
фактическая потеря данных с PITR: 0 заказов
фактическая потеря, будь только полный бэкап: 50 заказов
Два вывода. Первый: восстановление проверено — тест падает, если данные не сошлись, поэтому «бэкап работает» перестаёт быть верой. Второй: контраст показывает цену непрерывного архива — без него достижимая точка восстановления откатывается к моменту бэкапа и все 50 записанных после теряются; с ним точка подходит вплотную к катастрофе и потерь нет.
Две оговорки, без которых число вводит в заблуждение. Время здесь — это вся процедура: достать бэкап, подготовить конфиг восстановления, поднять инстанс, проиграть журнал, дождаться промоута. Мерить только старт инстанса некорректно — в реальном инциденте вы платите за всё. И это по-прежнему стенд: на реальной базе счёт идёт на минуты и десятки минут, а величина растёт с объёмом журнала, который надо проиграть от точки бэкапа.
Сценарии катастроф
Полезно проверять план не «вообще», а по конкретным сценариям — у каждого свой механизм защиты:
| сценарий | что помогает | что не помогает |
|---|---|---|
| отказ узла / зоны | HA, реплики, failover | — |
| потеря региона | копия и мощности в другом регионе | реплики внутри региона |
человеческая ошибка (DROP, миграция) |
PITR на точку до ошибки | репликация (ошибка доедет) |
| шифровальщик | неизменяемые offsite-копии | реплики и перезаписываемые бэкапы |
| тихая порча данных | ретроспективные копии + контроль целостности | свежий бэкап (в нём уже порча) |
Отдельного внимания стоит последняя строка: порча, замеченная через неделю, обесценивает недельные бэкапы. Поэтому глубина хранения — тоже часть RPO-разговора, а не только частота.
Мульти-регион
Когда сценарий «потеряли регион» реален, вариантов два:
- Active-passive — второй регион в горячем/тёплом резерве. Проще и дешевле; фактическое время восстановления здесь — время переключения, а достижимая точка восстановления определяется лагом репликации.
- Active-active — оба региона обслуживают трафик. Переключаться почти не нужно, поэтому механизм позволяет выполнить самый жёсткий целевой RTO, но платить приходится сложностью: конфликты записи, согласованность между регионами, риск split-brain.
Выбор диктуется тем же RTO/RPO: active-active оправдан, когда простой стоит дороже сложности. Про то, чем платят за согласованность между площадками, — в карте надёжности распределённых систем.
Runbook и учения
План, существующий только в голове, не работает в три часа ночи. Нужен runbook: пошаговая инструкция восстановления — откуда брать копии, в каком порядке поднимать, кто принимает решение о переключении, кого уведомить.
И его нужно репетировать: game day, учебная катастрофа на регулярной основе. Учения ловят то, что не видно на бумаге: истёкшие доступы, отсутствующий ключ шифрования, зависимость, о которой забыли, и слишком оптимистичный RTO. Что делать, когда катастрофа всё же случилась — как вести инцидент и разбирать его потом, — в статье про инциденты и постмортемыготовится, с 20 сентября.
Checklist
- RTO и RPO названы числами и согласованы с бизнесом, а не унаследованы по умолчанию.
- Понятно, что HA не покрывает: логическую ошибку, шифровальщика, потерю региона.
- Копии по правилу 3-2-1, одна — неизменяемая и вне площадки.
- Есть PITR (непрерывный журнал), а не только периодический полный бэкап.
- Restore гоняется автоматически и регулярно, с проверкой данных; фактическое время восстановления измерено и сопоставлено с целевым RTO, а не оценено на глаз.
- Глубина хранения покрывает сценарий «порчу заметили не сразу».
- Есть runbook и регулярные учения; известно, кто принимает решение о переключении.
Первоисточники
- PostgreSQL: непрерывное архивирование и PITR — механика восстановления на точку.
- Google SRE Book, гл. 26 «Data Integrity» — почему бэкап без восстановления бесполезен и как это проверяют.
- Все числа — со стенда architecture/resilience/dr.
Комментарии