Прямой ответ
Миграция без простоя выполняется как последовательность фаз, в каждой из которых сервис работает. Остановка не требуется, потому что старое и новое хранилища сосуществуют, а переключение выполняется изменением конфигурации.
Последовательность фаз:
1. Подготовка — новое хранилище развёрнуто, схема создана
2. Двойная запись — запись идёт в оба хранилища, чтение из старого
3. Перенос — существующие данные копируются в новое хранилище
4. Проверка — сверка количества и содержимого
5. Переключение чтения — чтение из нового, запись в оба
6. Стабилизация — наблюдение за новым хранилищем
7. Прекращение записи в старое — запись только в новое
8. Вывод старого хранилища
Ключевое свойство — каждая фаза обратима до седьмой. Пока запись идёт в оба хранилища, возврат чтения к старому выполняется изменением конфигурации за секунды; о механизме — в статье про двойную запись.
Точка невозврата — фаза 7. После прекращения записи в старое хранилище оно отстаёт, и возврат требует обратного переноса данных. Поэтому между фазами 5 и 7 выдерживают интервал.
Переключение чтения выполняется конфигурацией, а не развёртыванием:
storage:
read: "new" # было: "old"
write: ["old", "new"]
Изменение применяется без перезапуска либо быстрым перезапуском, поэтому откат занимает секунды. Это отличается от переключения через развёртывание новой версии, которое требует минут; о схемах развёртывания — в статье про blue-green.
Три условия корректности переключения.
1. Данные согласованы. Сверка подтверждает, что новое хранилище содержит те же данные; о методике — в статье про сверку.
2. Задержка нового хранилища не выше прежней. Переключение на более медленное хранилище деградирует сервис, и это обнаруживается только под нагрузкой.
3. Изменения во время переноса переданы. Запись, внесённая после начала переноса, должна попасть в новое хранилище через двойную запись либо репликацию.
Оценка длительности окна переключения
Время, в течение которого система недоступна либо работает с ограничениями, складывается из четырёх составляющих.
Применение накопившихся изменений. Разрыв между исходной и целевой базой за время сверки и подготовительных действий. Определяется интенсивностью записи и пропускной способностью механизма репликации.
Переключение маршрутизации. Изменение строки подключения либо конфигурации сервиса. Занимает секунды, но требует применения во всех экземплярах, поэтому зависит от способа распространения конфигурации.
Прогрев целевой базы. Первые запросы выполняются на холодном кеше, поэтому задержка выше установившейся. Прогрев выполняется чтением ключевых данных до переключения.
Принятие решения о завершении. Фиксация результата сверки и подтверждение готовности. Зависит от регламента, а не от техники.
Первые две составляющие измеримы и предсказуемы, третья оценивается по тестовому прогону, четвёртая определяется процедурой. Суммарное окно при подготовленной сверке составляет минуты, поскольку основная часть данных перенесена до переключения.
Критерий готовности — разрыв между базами ниже заданного порога при двух последовательных измерениях. Одно измерение может совпасть с периодом низкой нагрузки и не отражать установившийся разрыв.
Практика: переключение без простоя
1. Включайте двойную запись до начала переноса. Иначе изменения во время переноса попадут только в старое хранилище.
2. Переключайте чтение конфигурацией, а не развёртыванием. Скорость отката определяет риск переключения.
3. Проверяйте задержку нового хранилища до переключения. Сравнение выполняется под продуктивной нагрузкой, а не на тестовых данных.
4. Выдерживайте интервал перед прекращением двойной записи. Неделя наблюдения выявляет проблемы, которые не показала сверка.
5. Переключайте постепенно, если возможно. Часть трафика на новое хранилище позволяет сравнить поведение до полного переключения.
6. Фиксируйте точку невозврата в плане. Момент, после которого возврат требует переноса данных, определяется заранее.
7. Подготовьте обратный перенос. План возврата описывается до переключения, а не составляется в момент проблемы.
8. Мониторьте новое хранилище после переключения. Метрики задержки и ошибок сравниваются с прежними значениями.
Рекомендации:
- Не совмещайте миграцию с изменением схемы. Каждое изменение отдельно проще откатить и разобрать.
- Проверяйте откат на стенде. Возврат чтения к старому хранилищу должен выполняться и работать.
- Учитывайте кеш. Кеш, заполненный данными из старого хранилища, может отдавать устаревшие значения после переключения.
- Не удаляйте старое хранилище сразу. Оно нужно для возврата, а его удаление необратимо.
- Измеряйте длительность каждой фазы. Оценка времени нужна для планирования интервалов между фазами.
Практический сценарий: возврат к старому хранилищу после переключения чтения
Контекст: сервис перевели на новую базу. Через три часа после переключения чтения задержка части запросов выросла, и чтение вернули на старое хранилище.
- Диагностика. Новая база работала на экземпляре меньшего размера, чем старая. Под продуктивной нагрузкой задержка запросов с соединениями превысила прежнюю в несколько раз. Тестирование выполнялось на объёме в десять раз меньше продуктивного.
- Причина. Задержка нового хранилища проверялась на тестовых данных, а не под продуктивной нагрузкой. Двойная запись к моменту переключения ещё работала, что позволило вернуть чтение без потери данных.
- Действия. (а) Чтение вернули на старое хранилище изменением конфигурации, что заняло менее минуты; (б) двойную запись сохранили, поэтому данные продолжали попадать в оба хранилища; (в) новой базе увеличили ресурсы и создали отсутствующие индексы, выявленные по журналу медленных запросов; (г) добавили проверку задержки под нагрузкой, близкой к продуктивной; (д) повторное переключение выполнили через две недели после подтверждения задержки.
- Результат. Простой составил менее минуты вместо часов, которые потребовались бы при отсутствии двойной записи. Повторное переключение прошло без деградации.
Вывод: миграция без простоя держится на сосуществовании хранилищ и возможности быстрого возврата. Двойная запись до завершения стабилизации позволяет вернуть чтение изменением конфигурации, а проверка задержки под продуктивной нагрузкой предотвращает переключение на недостаточно мощное хранилище.
FAQ
Можно ли выполнить миграцию без двойной записи? Да, при использовании логической репликации либо CDC. Двойная запись проще, но требует сверки для обнаружения расхождений.
Когда прекращать запись в старое хранилище? После стабилизации нового хранилища под продуктивной нагрузкой. Обычно через одну-две недели после переключения чтения.
Что делать, если расхождение обнаружено после переключения? Вернуть чтение на старое хранилище, если запись в оба продолжалась. После прекращения двойной записи требуется обратный перенос.
Нужно ли останавливать сервис на время переноса данных? Нет. Перенос выполняется пакетами при работающем сервисе, а изменения во время переноса передаются двойной записью либо репликацией.
Источники: Martin Fowler (Parallel Change), PostgreSQL docs (Logical Replication), Kubernetes docs — ссылки в шапке.