119 lines
12 KiB
Markdown
119 lines
12 KiB
Markdown
---
|
||
aliases:
|
||
tags:
|
||
- зрелость/🌱
|
||
date:
|
||
- - 2024-05-28
|
||
zero-link:
|
||
- "[[00 MySQL]]"
|
||
parents:
|
||
- "[[Репликация БД]]"
|
||
linked:
|
||
- "[[Журналы в MySQL]]"
|
||
link: https://highload.guide/blog/asynchronous-replication.html
|
||
---
|
||
## Тезисы
|
||
- На slave можно реализовать другую схему БД, построить другие индексы.
|
||
- Можно использовать [libslave](libslave.md), чтобы "притвориться" репликой.
|
||
- Мастер многопоточен, а слейв - нет. Вроде исправлено в новых версиях SQL.
|
||
- В 5.6 версии можно реплицировать параллельно несколько БД
|
||
- В 5.7 версии можно реплицировать параллельно одни и те же таблицы
|
||
- Обязательно убедиться, что работают GUID идентификация транзакций.
|
||
***
|
||
|
||
|
||
**Репликация сильно зависит от версии MySql**
|
||
- Всегда логическая репликация, модель master-slave, pull распространение
|
||
- 4.1 = асинхронная, SBR, logposs
|
||
- 5.1 = +RBR, +mixed. Дефолт mixed
|
||
- 5.6 = +semisync, +mtslave (per-db), +slavedelay, +GTID
|
||
- 5.7 = + mtslave, +master-master (plugin), +default-RBR (image=full?!), groupcommit
|
||
|
||
## Схема работы репликации
|
||
![Архитектура MySQL](Архитектура%20MySQL.md#^42f122)
|
||
|
||
Такая плагинная архитектура позволяет устанавливать новый движок, но мгновенно возникает неоптимальность. В принципе, транзакционные write-ahead log'и (WAL), которые физический слой хранения все равно пишет, было бы хорошо использовать для репликации, и если система знает о том, что есть некий физический уровень, или достаточно хорошо сопряжена с этим физическим уровнем, то можно было бы отдельный лог на логическом уровне не писать, а использовать тот же самый WAL. Но у MySQL это невозможно концептуально, либо, если поменять интерфейс в PSE так, чтобы стало возможно концептуально, то будет очень много работы.
|
||
|
||
При включении репликации на логическом уровне MySQL мастер начинает вести binary log – файл, в который сыплются все подряд изменения.
|
||
|
||
У слэйва чуть больше работы. Помимо того, чтобы вести один дополнительный лог(relay log) и по запросу его рассылать, еще есть поток, который ходит к удаленному мастеру, возможно, даже не к одному, и качает оттуда binary log'и. Еще отдельный поток пытается исполнять эти локальные логи.
|
||
|
||
![](Pasted%20image%2020240712083105.png)
|
||
|
||
**Процесс записи данных операции в MySQL**
|
||
- INSERT INTO test VALUES (123, 'hello')
|
||
- Записываем в таблицу на мастере mysqld
|
||
- Записываем в binary log на мастере
|
||
- Записываем в relay log на слейве
|
||
- таблица на слейве mysqld
|
||
|
||
Что конкретно попадает в binary log, зависит от настроек журнала.
|
||
|
||
Рабочие потоки ([MySQL Replication Threads](https://dev.mysql.com/doc/refman/8.0/en/replication-threads.html)):
|
||
- binlog dump thread. Сохраняет лог транзакций на master
|
||
- slave I/O thread. Спуливает изменения на slave с master
|
||
- slave SQL thread. Применяет изменения на slave
|
||
|
||
Варианты репликаций:
|
||
- [Statement Based Replication (SBR)](Statement%20Based%20Replication%20(SBR).md)
|
||
- [Row Based Replication (RBR)](Row%20Based%20Replication%20(RBR).md)
|
||
- [Mixed binlog format](Mixed%20binlog%20format.md)
|
||
|
||
MySQL не решает из коробки проблемы кластеризации. Из коробки нет переключений со slave на master если мастер сдох, распределения нагрузки и так далее. Можно решить дополнительным софтом:
|
||
- MHA (MySQL Master HA)
|
||
- MySQL Failover (Oracle)
|
||
- Orchestrator
|
||
## Фильтрация репликации
|
||
Можно реплицировать данные частично, но это стоит использовать осторожно. Например, это не работает с [Групповая репликация](Групповая%20репликация.md)
|
||
|
||
Опции:
|
||
- replicate_do_db
|
||
- replicate_ignore_db
|
||
- replicate_do_table
|
||
|
||
[MySQL - CHANGE REPLICATION FILTER Statement](https://dev.mysql.com/doc/refman/8.0/en/change-replication-filter.html)
|
||
|
||
![](Pasted%20image%2020240605091913.png)
|
||
|
||
|
||
***
|
||
|
||
- В InnoDB, заметьте, т.е. у нас архитектура разделяет репликацию выше, а storage engine ниже. Но storage engine, для того, чтобы репликация работала, должен, грубо говоря, замедлять insert'ы в таблицу.
|
||
- Другая проблема состоит в том, что мастер выполняет запросы параллельно, т.е. одновременно, а слэйв их может применять последовательно. Возникает вопрос – а почему слэйв не может применять их параллельно? На самом деле, с этим все непросто. Есть теорема о сериализации транзакций, которая рассказывает, когда мы можем выполнять запросы параллельно, а когда последовательно. Это отдельная сложная тема, разберитесь в ней, если вам интересно и нужно, например, почитав по ссылке – [http://plumqqz.livejournal.com/387380.html](http://plumqqz.livejournal.com/387380.html).
|
||
- В MySQL репликация упирается в процессор. Это прекрасная картинка – большой, мощный сервер, 12 ядер. Работает одно ядро, заодно занято репликацией. Из-за этого реплика задыхается. Это очень грустно.
|
||
|
||
Для того чтобы выполнять запросы параллельно существует группировка запросов. В InnoDB есть специальная опция, которая управляет тем, как именно мы группируем транзакции, как именно мы их пишем на диск. Проблема в том, что мы можем их сгруппировать на уровне InnoDB, а уровнем выше – на уровне репликации – этой функциональности не было. В 2010 г. Кристиан Нельсен из MariaDB реализовал такую фичу, которая называется Group Binary Log Commit. Получается, мы журнал повторяем на двух уровнях – Storage Engine и репликация, и нам нужно таскать фичи из одного уровня на другой. Это сложный механизм. Более того, нам нужно одновременно консистентно писать сразу в два журнала – two-phase-commit. Это еще хуже.
|
||
|
||
На следующей картинке мы видим два графика:
|
||
![](Pasted%20image%2020240528090119.png)
|
||
Синий график демонстрирует то, как масштабируется InnoDB, когда мы ему добавляем треды. Накидываем треды – число транзакций, которые он обрабатывает, возрастает. Красная линия показывает ситуацию, когда включена репликация. Мы включаем репликацию и теряем масштабируемость. Потому что лог в Binary Log пишется синхронно, и Group Binary Log Commit это решает.
|
||
|
||
Грустно, что приходится так делать из-за разделения – Storage Engine внизу, репликация наверху. С этим все плохо. В MySQL 5.6 и 5.7 эта проблема решена – есть Group Binary Log Commit, и мастер теперь не отстает. Теперь это пытаются использовать для параллелизма репликации, чтобы на слэйве запросы из одной группы запустить параллельно. Тут я написал, что из этого нужно крутить:
|
||
|
||
![](Pasted%20image%2020240528090205.png)
|
||
|
||
|
||
## Параллельная репликация
|
||
Сценарий ([Estimating potential for MySQL 5.7 parallel replication](https://www.percona.com/blog/estimating-potential-for-mysql-5-7-parallel-replication/)):
|
||
- 1 мастер, 3 слейва
|
||
- первый реплицирует в 1 поток
|
||
- второй в 20 потоков
|
||
- третий в 100 потоков
|
||
- вставка в 25 различных таблиц внутри одной базы в 100 потоков
|
||
|
||
![](Pasted%20image%2020240606094633.png)
|
||
|
||
Полезные опции:
|
||
- sysvar_replica_parallel_workers - количество потоков
|
||
- sysvar_replica_parallel_type
|
||
- DATABASE - транзакции применяются параллельно, если они обновляют разные БД
|
||
- LOGICAL_CLOCK - транзакции применяются параллельно на реплике на основе timestamp
|
||
## Отставание реплики
|
||
- [Отставание реплики в БД](Отставание%20реплики%20в%20БД.md)
|
||
|
||
Диагностировать причину отставания реплики тяжело. Есть средство диагностики в MySQL, называется log медленных запросов. Вы можете его открыть, найти топ самых тяжелых запросов и исправить их. Но с репликацией это не работает. Нужно проводить статистический анализ – считать статистику – какие таблицы стали чаще использоваться. Вручную это сделать очень тяжело.
|
||
|
||
В MySQL 5.6 / 5.7 появилась SLAVE PERFORMANCE SCHEMA, на базе которой такую диагностику провести проще. Мы обычно открываем лог коммитов в puppet и смотрим, что же мы выкатили в то время, когда репликация начала отставать. Иногда даже это не помогает, приходится ходить по всем разработчикам и спрашивать, что они сделали, они ли сломали репликацию. Это грустно, но с этим приходится жить.
|
||
|
||
## Дополнительные материалы
|
||
- [Как устроена MySQL-репликация / Андрей Аксенов (Sphinx) - YouTube](https://www.youtube.com/watch?v=lHFaZkJk2O0) |