Продолжаем разбирать кабанчика («Высоконагруженные приложения» Мартина Клепманна). Глава 5 открывает вторую часть книги — про распределенные данные. В этой главе рассказывается о репликации. Глава насыщенная, поэтому разбила её на несколько постов.
Репликация — это хранение копий одних и тех же данных на нескольких серверах, которые соединены между собой сетью.
Зачем может быть нужна репликация:
✅ для повышения доступности (если один сервер вышел из строя, можно переключиться на реплику)
✅ для повышения пропускной способности запросов — горизонтального масштабирования (запросы на чтение можно направлять не на один сервер, а распределить между репликами)
✅ для уменьшения задержек при выполнении запросов в случае географической удаленности (если сервер находится далеко, можно поставить реплику поближе к пользователям)
Репликация с одним ведущим узлом
Одна из узлов назначается лидером (leader, master, primary). Запросы на запись в БД поступают лидеру.
Остальные узлы называются ведомыми или репликами (followers, read replicas, secondaries). Каждый раз, когда лидер записывает себе новые данные, он также отправляет информацию об изменениях данных всем репликам. Реплики получают данные от лидера и обновляют соответствующим образом свою локальную копию БД, применяя все операции записи в порядке их обработки лидером.
Запросы от клиентов на чтение из БД могут направляться как к лидеру, так и к любой реплике. Запросы на запись направляются только лидеру.
Такой режим репликации встроен во многие БД: PostgreSQL, MySQL, MongoDB и др. Репликация с ведущим узлом применяется не только в базах: Kafka и RabbitMQ тоже его применяют.
Способы реализации репликации
🎮 Операторная репликация
Лидер записывает в журнал каждый выполняемый запрос на запись (INSERT, UPDATE, DELETE) и отправляет этот журнал репликам. Каждая реплика производит синтаксический разбор и выполнение этого оператора SQL так, как если бы он был получен от клиента.
Для функций типа NOW() надо заменить в журнале вызов функции на значение, сгенерированное на лидере.
Если операторы используют поле с инкрементом или зависят от существующих данных (UPDATE … WHERE…), то они должны выполняться на всех репликах в строго одинаковом порядке, иначе их результаты будут различными. Это важно учитывать в случае параллельных транзакций.
🔼Перенос WAL
Лидер отправляет репликам данные из своего журнала предзаписи (write-ahead log — WAL), который содержит не операторы, а результаты всех операций записи в БД (какие байты меняются в каких блоках). Реплики создают точные копии тех же структур данных, что и на лидере.
Этот метод репликации используется в PostgreSQL и Oracle.
Из-за описания данных на очень низком уровне лидер и реплики должны иметь одну версию БД, соответственно их придется обновлять одновременно с простоем системы.
➡️ Логическая (построчная) репликация
В этом случае журнал содержит описания операций записи на уровне строк:
🔹при вставке строки — новые значения всех полей
🔹при удалении строки — идентификатор удаляемой строки
🔹при обновлении строки — идентификатор удаляемой строки и новые значения всех (или только изменившихся) полей
🔹при транзакции — запись о ее фиксации
В случае логической репликации на лидере и репликах могут быть разные версии БД. Формат логического журнала может быть удобнее для синтаксического разбора внешними приложениями, которые следят за изменениями в БД (change data capture).
🔔 Триггерная репликация
В этом случае репликация поднимается на уровень кода приложения. Мы создаем триггер, который срабатывает в случае изменения данных в БД и сохраняет изменения в отдельную таблицу. Далее отдельный процесс приложения читает эту таблицу и выполняет любую логику, которая нужна. Например, передает изменения данных в другую систему.
#кабанчик #сисдиз
Post #53
1.72K
- 👍 8
- ❤ 5
- 🔥 2