Статьи

Репликация с несколькими источниками в MySQL 5.7 против Tungsten

MySQL 5.7 поставляется с новым набором функций, и одна из них — репликация из нескольких источников. В нескольких словах это означает, что один раб может копировать от разных мастеров одновременно.

В течение последних нескольких месяцев я много играл с этим, пытаясь проанализировать его потенциал в реальном случае, с которым я столкнулся при работе с клиентом.

Это было мотивировано, потому что мой клиент уже использует ведомые устройства с несколькими источниками с Tungsten Replicator, и я хотел сделать параллельное сравнение между Tungsten Replicator и Multi-source Replication в MySQL 5.7

Рассмотрим следующий сценарий

смешанный
DB1 является нашим главным мастером, обслуживающим в основном записи из нескольких приложений, он также должен обслуживать трафик чтения, что приближает его емкость к пределу. Он подключил 6 подчиненных репликаций с использованием обычной репликации.
A1, A2, A3, B1, B2 и DB7 являются подчиненными подчиненными, используемыми для разгрузки некоторых чтений с главного устройства, а также просыпаются в некоторых автономных процессах ETL.

Поскольку у них была свободная емкость, клиент решил пойти дальше и установить другую архитектуру:
A1 и B1 стали также хозяевами других ведомых устройств, использующих Tungsten Replicator, в этом случае группа A представляет собой набор серверов для приложения статистики, а B посещает финансовый отдел. приложение, поэтому A2, A3 и B2 стали рабами с несколькими источниками.
Новые приложения записывают напрямую в A1 и B1, не влияя на емкость записи основного мастера.

Плюсы и минусы этого подхода

Pros

  • Это просто работает. Мы работали так давно, и у нас не было серьезных проблем.
  • В Tungsten Replicator есть несколько встроенных инструментов и скриптов, которые упрощают подчиненное управление.

Cons

  • Tungsten Replicator — отличный продукт, но больше, чем нужно для этой архитектуры. В некоторых случаях нам приходилось настраивать виртуальную машину Java с 4 ГБ ОЗУ для правильной работы.
  • Tungsten — это сложный инструмент, для развертывания которого требуется дополнительная экспертиза, чтобы он работал и устранял проблемы, возникающие при возникновении ошибок (например, обработка ошибок дублирующихся ключей).

Имея все это в виду, мы сделали шаг вперед и начали проверять, можем ли мы переместить эту архитектуру для использования только устаревшей репликации.

Новый архитектурный дизайн
Пустая блок-схема - новая страница (7)

Мы добавили некоторую емкость хранилища в DB7 для наших целей тестирования, и цель здесь состоит в том, чтобы заменить все реплицированные вольфрамовые ведомые устройства одним сервером, на котором консолидируются все базы данных.

Для некоторой зависимости от данных мы не смогли полностью разделить серверы A1 и B1, чтобы стать только ведущими, поэтому они в настоящее время действуют как хозяева DB7 и подчиненные устройства DB1. Под зависимостью от данных я имею в виду, что DB1 реплицирует свои схемы всем своим прямым подчиненным, в том числе DB7. DB7 также получает репликацию финансовой базы данных, работающей локально, на B1 и статистики DB, работающей локально на A1.

Как это было сделано и что реализовано в нескольких источниках

  • Основное различие между обычной репликацией, известной до версии 5.6, заключается в том, что теперь у вас есть каналы репликации, каждый канал означает другой источник, другими словами, у каждого мастера есть свой собственный канал репликации.
  • Репликация должна быть настроена как безопасная для отказа, а это означает, что  master_info_repository и relay_log_info_repositoryпеременные, и переменные должны быть установлены вTABLE
  • Мы не рассматривали GTID, потому что серверы, действующие как мастера, имеют версии, отличные от нашего тестового ведомого ведомого с несколькими источниками.
  • log_slave_updates необходимо отключить в A1 и B2, чтобы избежать дублирования данных в DB7 из-за потока репликации.

Плюсы и минусы этого подхода

Pros

  • MySQL 5.7 может реплицироваться из разных версий master, мы тестировали многоисточниковую репликацию, работающую одновременно с 5.5 и 5.6, и не испытывали проблем, кроме тех известных изменений с полями, основанными на отметке времени.
  • Администрация становится проще. Любой администратор базы данных, уже знакомый с унаследованной репликацией, может адаптироваться для работы с несколькими каналами без особого изучения, каких-то новых переменных и пары новых таблиц, и вы готовы к этому.

Cons

  • 5.7 еще не готов к производству. На данный момент у нас нет данных о выпуске GA, что означает, что мы можем ожидать появления ошибок в краткосрочной / среднесрочной перспективе.
  • С несколькими источниками все еще сложно в некоторых особых случаях: фильтрация базы данных и таблиц работает глобально (не могут устанавливать фильтры для каждого канала), а команды администрирования, такие sql_slave_skip_counterкак глобальная команда, все еще означают, что вы не можете легко пропустить оператор в определенном канале ,

Теперь забавная часть: как

Это было проще, чем вы думаете. Прежде всего нам нужно было начать с резервного копирования данных, поступающих от наших мастеров. Из-за версий, используемых в производстве (основной мастер — 5,5, А1 и В1 — 5,6), мы начали с логического дампа, поэтому мы избежали решения проблем mysql_upgrade.

Отказ от ответственности: это не претендует на то, как настроить репликацию из нескольких источников

Для нашего случая мы сделали резервное копирование / восстановление, используя mydumper / myloader следующим образом:

[root@db1]$ mydumper -l 600 -v 3 -t 8 --outputdir /mnt/backup_db1/20150708 --less-locking --regex="^(database1.|database2.|database3.)"
[root@a1]$ mydumper -l 600 -v 3 -t 8 --outputdir /mnt/backup_a1/20150708 --less-locking --regex="^(tungsten_stats.|stats.)"
[root@b1]$ mydumper -l 600 -v 3 -t 8 --outputdir /mnt/backup_b1/20150708 --less-locking --regex="^(tungsten_finance.|finance.)"

Обратите внимание, что каждая команда была запущена на каждом главном сервере, теперь часть восстановления:

[root@db7]$ myloader -d /mnt/backup_db1/20150708  -o -t 8 -q 10000 -h localhost
[root@db7]$ myloader -d /mnt/backup_a1/20150708 -o -t 8 -q 10000 -h localhost
[root@db7]$ myloader -d /mnt/backup_b1/20150708 -o -t 8 -q 10000 -h localhost

Таким образом, на данный момент у нас есть новый ведомый с копией баз данных от 3 разных мастеров, просто для контекста нам нужно создавать / восстанавливать базы данных Tungsten *, потому что они постоянно обновляются Replicator (который на данный момент все еще используется). Довольно легко, верно?

Теперь самая важная часть всего этого процесса, настройка репликации. Процедура очень похожа на обычную репликацию, но теперь нам нужно рассмотреть, какая позиция бинлога необходима для каждого канала репликации, это очень легко получить из каждой резервной копии, прочитав в этом случае файл метаданных, созданный mydumper. В известных способах резервных копирования (или логический или физический) у вас есть способ получить Двоичные координаты, например -МАСТЕР-данные = 2 в туздЫшпре или xtrabackup_binlog_info файла в XtraBackup.

Как только мы получим информацию о репликации (и создадим пользователя репликации в master), нам нужно только запустить известные команды CHANGE MASTER TOи START SLAVEкоманды, но здесь у нас есть новый способ сделать это:

db7:information_schema> change master to master_host='db1', master_user='rep', master_password='rep', master_log_file='db1-bin.091487', master_log_pos=74910596 FOR CHANNEL 'main_master';
       Query OK, 0 rows affected (0.02 sec)
db7:information_schema> change master to master_host='a1', master_user='rep', master_password='rep', master_log_file='a1-bin.394460', master_log_pos=56004 FOR CHANNEL 'a1_slave';
       Query OK, 0 rows affected (0.02 sec)
db7:information_schema> change master to master_host='b1', master_user='rep', master_password='rep', master_log_file='b1-bin.1653245', master_log_pos=2563356 FOR CHANNEL 'b1_slave';
       Query OK, 0 rows affected (0.02 sec)

Репликация установлена, и теперь мы готовы идти:

db10:information_schema> START SLAVE FOR CHANNEL 'main_master';
       Query OK, 0 rows affected (0.00 sec)
db10:information_schema> START SLAVE FOR CHANNEL 'a1_slave';
       Query OK, 0 rows affected (0.00 sec)
db10:information_schema> START SLAVE FOR CHANNEL 'b1_slave';
       Query OK, 0 rows affected (0.00 sec)

Новые команды включают FOR CHANNEL 'channel_name'возможность обрабатывать каналы репликации независимо

На этом этапе у нас есть подчиненное устройство, запускающее 3 канала репликации из разных источников, мы можем проверить состояние репликации с помощью нашей известной команды SHOW SLAVE STATUS(TL; DR).

db10:information_schema> show slave statusG
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: db1
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: db1-bin.077011
          Read_Master_Log_Pos: 15688468
               Relay_Log_File: db7-relay-main_master.000500
                Relay_Log_Pos: 18896705
        Relay_Master_Log_File: db1-bin.076977
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table: mysql.%,temp.%
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 18896506
              Relay_Log_Space: 2260203264
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 31047
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1004
                  Master_UUID: 65107c0c-7ab5-11e4-a85a-bc305bf01f00
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: System lock
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name: main_master
*************************** 2. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: a1
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: a1-bin.072336
          Read_Master_Log_Pos: 10329256
               Relay_Log_File: db7-relay-db3_slave.000025
                Relay_Log_Pos: 10329447
        Relay_Master_Log_File: a1-bin.072336
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table: mysql.%,temp.%
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 10329256
              Relay_Log_Space: 10329697
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 4000
                  Master_UUID: 0f061ec4-6fad-11e4-a069-a0d3c10545b0
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name: a1_slave
*************************** 3. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: b1.las1.fanops.net
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: b1-bin.093214
          Read_Master_Log_Pos: 176544432
               Relay_Log_File: db7-relay-db8_slave.000991
                Relay_Log_Pos: 176544623
        Relay_Master_Log_File: b1-bin.093214
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table: mysql.%,temp.%
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 176544432
              Relay_Log_Space: 176544870
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1001
                  Master_UUID:
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name: b1_slave
3 rows in set (0.00 sec)

Да, я знаю, что вывод слишком велик, и ребята из Oracle тоже это заметили, поэтому они создали набор новых таблиц в БД performance_schema, чтобы помочь нам получить эту информацию в дружественной манере, проверьте эту ссылку для получения дополнительной информации. Мы могли бы также запустить, SHOW SLAVE STATUS FOR CHANNEL 'b1_slave'например,

Некоторые ограничения, найденные во время испытаний

  • Как уже упоминалось, некоторые конфигурации все еще являются глобальными и не могут быть установлены для каждого канала репликации, например фильтры репликации, которые можно установить без перезапуска MySQL, но они будут влиять на все каналы репликации, как вы можете видеть здесь.
  • События репликации каким-то образом сериализуются на ведомой стороне, как глобальный счетчик, который еще недостаточно документирован. В действительности это означает, что вам нужно быть очень осторожным при устранении неполадок, потому что вы можете столкнуться с неожиданными проблемами, например, если у вас 2 канала репликации, выходящие из строя с ошибкой дублирующегося ключа, тогда нелегко предсказать, что вы даже пропустите при запуске set global SQL_SLAVE_SKIP_COUNTER = 1

Выводы

Пока что эта новая функция выглядит очень красиво и обеспечивает некоторую дополнительную гибкость для подчиненных, что помогает уменьшить сложность архитектуры, когда мы хотим объединить базы данных из разных источников на одном сервере. После некоторого времени тестирования я бы сказал, что я предпочитаю этот тип репликации вместо Tungsten Replicator в таких сценариях, потому что это просто для администрирования, то есть pt-table-checkum и pt-table-sync будут работать без надлежащих ограничений Tungsten.

За исключением некоторых ограничений, которые необходимо устранить, я считаю, что эта новая функция меняет игру и, безусловно, облегчит жизнь администраторам баз данных. Мне еще предстоит многое проверить, но это материал для будущего поста.

Автор  Франсисо Борденаве .