Недавно по основной работе у меня появилась задача по изучению процесса миграции данных между базами. Решил поделиться с сообществом своими исследованиями в сфере миграции, полученными в рамках этой задачи.
Содержание статьи:
Введение
Миграция баз данных: с чего начать
Зачем нужна миграция?
PoC: с чего начать?
4.1 PoC: одинаковые парадигмы
4.2 PoC: разные парадигмыТестируй пока не стало поздно
Стратегии миграции
6.1 Холодная миграция
6.2 Горячая миграцияЗаключение
Примечание: что нужно знать
Если ты только начинаешь знакомство с базами данных в общем или в частности, возможно, стоит начать с прочтения моей предыдущей статьи "Database 101: Data Consistency for Beginners". Эта статья охватывает мое собственное исследование того, сколько существует парадигм баз данных. В ней я заглядываю за пределы моего предыдущего опыта только с SQL и MySQL.
1. Пролог
С тех пор, как я начал свой путь в «мире баз данных», я задал себе очень много вопросов, на ответы на которые, вероятно, уйдет несколько лет. Но на один из этих вопросов — "Как правильно выполнить миграцию базы данных?", у меня до сих пор нет ответа.
Когда я мигрировал бота своего сообщества He4rt Developers, я приложил все усилия, чтобы сделать весь бекенд и саму модель базы данных максимально идеальными. Но когда мне пришлось все мигрировать, это был провал. Я решил использовать подход "Big Bang" (пул реквест с изменением 532 файлов). Это было одним из моих самых ужасных решений в open source.
В то время у меня вообще не было никаких знаний по теме миграции баз данных. Но урок был очень полезным.
2. Миграция баз данных: с чего начать
А у тебя когда-нибудь была задача, заключающаяся в том, чтобы исследовать процесс того, как правильно мигрировать данные из одной базы в другую? В этой теме следует знать несколько вещей, прежде чем делать что-либо, связанное с кодом.
Что я имею в виду? Просто перекидывать запросы между базами данных — это не то, с чего следует начинать.
Прежде всего, нужно задать себе несколько вопросов:
Зачем нужна миграция базы данных?
Какой подход к миграции следует использовать в проекте?
Собираемся ли мы прыгать от одной парадигмы к другой?
Дает ли новая база данных необходимую поддержку того, что мы используем сейчас в старой?
Имея в виду эти четыре вопроса можно начинать ресерч. В рамках ресерча нужно на них ответить, и только затем приступать к запросам/коду.
3. Зачем нужна миграция?
Когда речь идет о замене какой-либо части стека работающего проекта, причина должна быть ясна всей команде, которая планирует это масштабное изменение внутри продукта.
Так в чем же причина миграции? Есть такие примеры вариантов:
Уменьшение latency при вводе-выводе;
Понижение стоимости поддержки;
В целом современность базы данных, помогающая развивать продукт быстрее и дешевле.
Это всего лишь несколько вариантов в огромном списке причин замены базы данных. Но причины конкретного кейса точно надо знать на старте.
4. PoC (проверка концепции): с чего начать?
Итак, у нас есть четкое понимание причин миграции. Теперь нужно определиться с вещами, важными для того, чтобы все заработало и прошло по плану. Знаешь ли ты разницу между парадигмами баз данных? При переносе данных между разными базами нужно постоянно держать руку на пульсе. Давайте разберемся, какой тип PoC лучше использовать в конкретных кейсах.
4.1 PoC: одинаковые парадигмы
Представим несколько сценариев миграции:
CassandraDB → ScyllaDB (колоночные БД);
MySQL → PostgreSQL (реляционные БД);
Memcache → Redis (БД ключ-значение);
MongoDB → DynamoDB или Firebase (документно-ориентированные БД).
Во всех этих сценарии данные мигрировать легче, потому что они используют одну и ту же парадигму баз данных, а значит - придерживаются одной и той же архитектуры.
Они имеют в основном одинаковые функции, индексацию и типы данных. Возможно, будут небольшие различия, но с ними можно справиться, выполнив тесты и перейдя от одной функции/типа данных к другой.
Даже когда Discord мигрировал по сценарию из первого примера в процессе былы проблемы. Но, в конце концов, все прошло намного проще, чем в случае миграции между разными парадигмами. Если возникают проблемы во время PoC - это всего лишь часть работы.
4.2 PoC: разные парадигмы
А что если задача состоит в том, чтобы перейти от документно-ориентированный базы к колоночной? Звучит как сложная задача, и, вероятно, так оно и будет, и эта часть требует особенно тщательного проектирования. Когда Discord начал мигрировать от документно-ориентированный базы к колоночной в 2017 году, у них возникла та же проблема.
Как разделить бесконечный объект JSON? Есть идеи? Пример JSON:
{
"servers": [
{
"218378123781": {
"id": "218378123781",
"server_name": "He4rt Developers",
"channels": [
{
"78931278921723": {
"name": "Test Channel 1",
"messages": [
{
"312783712867": {
"message_id": "312783712867",
"chatter_id": "danielhe4rt",
"content": "oh hi lol",
"created_at": "1691972222",
"updated_at": "1691972222"
}
},
{
"312783712867": {
"message_id": "312783712867",
"chatter_id": "danielhe4rt",
"content": "oh hi lol",
"created_at": "1691972222",
"updated_at": "1691972222"
}
}
]
}
}
]
}
}
],
"users": [
{
"danielhe4rt": {
"chatter_id": "danielhe4rt",
"joined_at": "1691972222"
}
},
{
"dont_forget_to_follow_me_on_socials": {
"chatter_id": "dont_forget_to_follow_me_on_socials",
"joined_at": "1691972222"
}
}
]
}
Примерно так все выглядит в кейсе с Discord. Да, это далеко от реальности, но остановимся на этом примере. И, честно говоря, если у тебя есть хороший администратор баз данных и крутые архитекторы, то это не будет проблемой.
Во-первых, нужно, чтобы вся команда как можно больше знала о старой и о новой парадигмах и о том, как их использовать. При документно-ориентированном подходе можно работать со всем, чем угодно, потому что нет строгой согласованности данных. Но при переходе на колоночную БД нужно будет моделировать таблицы, обращать внимание на типы запросов, а также понимать, как работают «уровень согласованности» и «коэффициент репликации».
В конце должно получиться что-то вроде:
CREATE TABLE servers (
server_id bigint
owner_id text
server_name text,
created_at timestamp,
PRIMARY KEY (server_id, created_at)
);
CREATE TABLE channels (
server_id bigint
channel_id bigint
channel_name text,
created_at timestamp
PRIMARY KEY ((server_id), created_at)
) WITH CLUSTERING ORDER BY (created_at DESC);
CREATE TABLE channel_messages (
message_id bigint
channel_id bigint,
chatter_id text,
content text,
created_at timestamp,
PRIMARY KEY ((message_id, channel_id), created_at)
) WITH CLUSTERING ORDER BY (created_at DESC);
CREATE TABLE users (
user_id text,
user_name text,
created_at timestamp,
PRIMARY KEY (user_id, created_at)
);
Да, CQL (Cassandra Query Language) очень похож на SQL.
5. Тестируй пока не стало поздно
Хорошо, мы провели проверку концепции и знаем, какая база данных и парадигма лучше всего подойдут для новой среды. Теперь команда сосредоточена на том, чтобы как можно скорее завершить моделирование данных. Как только это будет сделано, основное внимание будет уделено подготовке всех сценариев для успешной миграции.
Лучшее, что можно сделать, — это провести тесты с 1% и 5% вашей базы данных в стейдж-среде. Почему? Если «новая система» или «новая версия» системы крашнется с 1% базы данных, это будет означать, что чего-то не хватает в моделировании данных или даже в серверной части. Итак, на этом этапе нужно остановить сценарии миграции и написать несколько тестов для приложения.
Теперь, когда с 1% базы процесс закончен, следует проделать то же самое с 5%. На этом этапе следует все тщательно протестировать, поскольку это последний шаг тестирования, который делается перед финализацией стратегии миграции и ее выполнением.
6. Стратегии миграции
Миграция между базами данных далеко не нова, есть лучшие практики, облегчающие жизнь. А еще есть несколько правил, которые помогут провести миграцию на профессиональном уровне.
Существует две очень популярные стратегии: «Горячая миграция» и «Холодная миграция». Сами названия стратегий как бы намекают на вопрос, который я задавал себе с самого начала работы над этой задачей: следует ли мне отключить текущую базу или будет ок выполнить миграцию прямо во время ее работы? На самом деле все зависит от потребностей. В любом случае, сам процесс называется ETL (извлечение, преобразование, загрузка).
6.1 Холодная миграция
Начнем с «самой простой» и безопасной миграционной стратегии: «холодная миграция». Причина использования этого типа миграции заключается в том, что можно без проблем остановить свою систему на необходимое время. По сути, нужно запланировать период обслуживания и сообщить об этом пользователям. Такая миграция также может называться как «миграция большого взрыва», ведь она полностью перенесет все данные в новую среду, в которой ранее ничего не было.
Этот подход используется в малых/средних компаниях/инфраструктурах и обычно выполняется поздней ночью, когда система нужна наименьшему числу пользователей.
Существует контрольный список вещей, о которых следует знать при выполнении холодной миграции:
Планирование: в какое время суток и кто будет отвечать за выполнение этой задачи?
Извлечение: как мы собираемся выгрузить все данные? Возможно, в целевой базе данных уже есть специальные инструменты, которые будут использоваться.
Трансформация: соответствуют ли данные форме новой базы данных? Обе базы данных имеют одинаковую структуру? Есть ли какой-нибудь инструмент для преобразования этих данных?
Загрузка: как убедиться в том, что новая база данных получила все данные? Что если есть сломанные запросы?
Проверка: все загрузили. Теперь нужно проверить, совпадают ли данные в новой базе с данным в старой.
Тестирование: подключим перенесенную базу данных в систему и запустим все тесты.
Активация: все хорошо. Теперь пришло время отключить устаревшую базу данных.
По сути, это флоу миграции, когда есть возможность все отключить.
6.2 Горячая миграция
Теперь переходим к более сложному сценарию, где необходимо вести запись данных одновременно в двух базах данных. Вместо одного экземпляра базы данных, у нас будет два, и это имеет важное значение.
Существует чек-лист, который поможет в этом процессе. Рассмотрим его этапы:
Планирование: Здесь необходимо обеспечить подходящую инфраструктуру для перехода между базами данных. В общем учитывать не только время суток.
Репликация: Оба системы должны синхронизироваться одновременно во время миграции.
Тестирование и проверка: Важно тщательно проверять данные, которые переносятся в процессе репликации. Особенно те, которые пишутся параллельно.
Минимизация простоев: Система должна оставаться онлайн постоянно, и пользователи не должны замечать никаких сбоев, даже при возникновении проблем.
Переключение: Когда все важные данные успешно перенесены, приложение будет переведено на новую базу данных.
Активация: Все идет по плану, и теперь можно отключить старую базу данных.
Эта стратегия миграции рекомендуется компаниям, которые зависят от непрерывной доступности и предоставляют критически важные сервисы, которые нельзя просто так остановить.
7. Заключение
Надеюсь, что это мини-интро поможет тебе лучше разбираться в особенностях миграции баз данных.
Спасибо.