Настройка репликации Master-Master на MySQL
Репликация в виде Master-Master в MySQL используется распределения нагрузки на БД между нодами. С помощью репликации, 2 (и больше) отдельных MySQL серверов выступают в качестве кластера. Кластеризация базы данных особенно полезна для обеспечения высокой производительности. Используйте два и более выделенных серверов (нод) для настройки репликации базы данных ( но для этого нужно выделенные IPv4 адреса).
В mysql существует два типа репликации данных:
- Master-Slave
- Master-Master
При использовании репликации Master-Slave, на Master ноде данные поступают ( с ними можно выполнять любые операции (добавлять/удалять/изменять) и все изменения Slave нода будет забирать себе, но если на Slave ноде вы выполните любой из запросов ( удаление, добавление или изменение), то данные не попадут на Master.
При репликации в виде Master-Master данные попавшие на ноды, будут синхронизироваться между собой.
Имеется:
- (Мастер 1) — Сервер с ОС Debian 8 — 192.168.13.147
- (Мастер 2) — Сервер с ОС CentOS 7 -192.168.13.151
Взял специально 2 сервера с разными ОС для того чтобы показать что оно может работать корректно ( можно использовать не ограниченное количество нод, хоть 100 шт).
Данный процесс настройки master-master репликации поделен на 2 шага:
- На 1-м шаге, организую master-slave репликацию, где главным будет master_1, а подчиненным будет master_2;
- На 2-м шаге я организую обратную master-slave репликацию, и сервера начинают собирать информацию из логов друг друга.
Установка MYSQL в Unix/Linux
У меня имеется ряд статей по установке mysql на различные Unix/Linux ОС, по этому если кто-то не знает как установить, может воспользоваться следующими статьями:
Установка MySQL на Debian/Ubuntu/Linux Mint
Установка MySQL 5.5 на RHEL / CentOS и Fedora
Установка MySQL из портов во FreeBSD
Установка MariaDB 10 на CentOS 7
Установка MariaDB 5.5 на RHEL / CentOS / Fedora Linux
Установка MariaDB в Ubuntu 12.04/12.10/13.04/13.10/14.04
Настройка репликации Master-Master на MySQL
И так, mysql установлен на всех серверах (у меня их 2, но можно подключить и больше) и следующим шагом нужно отредактировать my.cnf файл на каждой из нод.
На 1-м сервере с ОС Debian 8 (192.168.13.147):
# vim /etc/mysql/my.cnf
Вставляем:
[mysqld] #Уникальный идентификатор сервера server-id = 1 #Логи ошибок log_error = /var/log/mysql/mysql.err #Путь к bin-логам сервера(бинлог, который ведет мастер) log_bin = /var/log/mysql/mysql-bin.log log_bin_index = /var/log/mysql/mysql-bin.log.index #Путь к relay-логам слейва (бинлог, скачанный с мастера) relay_log = /var/log/mysql/mysql-relay-bin relay_log_index = /var/log/mysql/mysql-relay-bin.index #БД, которые нужно/не нужно реплицировать #replicate-do-db = testdb replicate-ignore-db=information_schema replicate-ignore-db=mysql replicate-ignore-db=performance_schema #Не вести журнал бин-лога для БД binlog-ignore-db = information_schema binlog-ignore-db = mysql binlog-ignore-db = performance_schema #Чтобы не было конфликтов автоинкремента, говорим серверу, #чтобы id генерировались начиная с 1-го прибавляя по 2, # например 13, 23, 33, 43... auto_increment_increment = 2 auto_increment_offset = 1 #Сохранять логи с мастера в своий бин-лог, чтобы передать слейву log-slave-updates #log_slave_updates = 1 # Сколько дней хранить бин-логи expire_logs_days = 7 # Максимальный размер бин-лога max_binlog_size = 500M # Адрес 1-го мастера bind-address = 192.168.13.147
В моем конфиге будет реплицироваться все БД, но если хотите сделать репликацию только 1 базы данных — стоит раскомментировать «binlog_do_db» поле и указать в нем имя БД.
Создаем пользователя для репликации:
mysql> create user 'replica'@'%' identified by '%repl2017'; Query OK, 0 rows affected (0.00 sec) mysql> grant replication slave on *.* to 'replica'@'%'; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) mysql> exit Bye [root@localhost captain]#
PS: Для более крутой безопасности, можно указать конкретно IP:
# create user 'replica'@'192.168.13.147' identified by '%repl2017'; # GRANT REPLICATION SLAVE ON *.* TO 'replica'@'192.168.13.147' IDENTIFIED BY '%repl2017';
Перезапускаем MySQL сервер:
# service mysql restart
Собственно, первый MASTER готов!
Смотрим статус мастера (данная информация понадобится немного позже):
mysql> show master status; +------------------+----------+--------------+---------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+---------------------------------------------+ | mysql-bin.000002 | 107 | | information_schema,mysql,performance_schema | +------------------+----------+--------------+---------------------------------------------+ 1 row in set (0.00 sec) mysql>
Вот.
На 2-м сервере с ОС CentOS 7 -192.168.13.151:
# vim /etc/my.cnf
Вставляем:
[mysqld] #Уникальный идентификатор сервера server-id = 2 #Логи ошибок log_error = /var/log/mysql/mysql.err #Путь к bin-логам сервера(бинлог, который ведет мастер) log_bin = /var/log/mysql/mysql-bin.log log_bin_index = /var/log/mysql/mysql-bin.log.index #Путь к relay-логам слейва (бинлог, скачанный с мастера) relay_log = /var/log/mysql/mysql-relay-bin relay_log_index = /var/log/mysql/mysql-relay-bin.index #БД, которые нужно/не нужно реплицировать #replicate-do-db = testdb replicate-ignore-db=information_schema replicate-ignore-db=mysql replicate-ignore-db=performance_schema #Не вести журнал бин-лога для БД binlog-ignore-db = information_schema binlog-ignore-db = mysql binlog-ignore-db = performance_schema #Чтобы не было конфликтов автоинкремента, говорим серверу, #чтобы id генерировались начиная с 2-го прибавляя по 2, # например 13, 23, 33, 43... auto_increment_increment = 2 auto_increment_offset = 2 #Сохранять логи с мастера в своий бин-лог, чтобы передать слейву log-slave-updates #log_slave_updates = 1 # Сколько дней хранить бин-логи expire_logs_days = 7 # Максимальный размер бин-лога max_binlog_size = 500M # Адрес 2-го мастера bind-address = 192.168.13.151
Создаем папку и файлы ( в них будут писаться логи):
# mkdir /var/log/mysql # chown -R mysql. /var/log/mysql
Создаем пользователя для репликации:
mysql> create user 'replica'@'%' identified by '%repl2017'; grant replication slave on *.* to 'replica'@'%'; flush privileges; exit
PS: Для более крутой безопасности, можно указать конкретно IP:
# create user 'replica'@'192.168.13.147' identified by '%repl2017'; # GRANT REPLICATION SLAVE ON *.* TO 'replica'@'192.168.13.147' IDENTIFIED BY '%repl2017';
Перезапускаем MySQL сервер:
# service mysqld restart
Идем дальше.
Настройка репликации
Сейчас нужно настроить саму репликацию. Для начала, запускаем репликацию на 2-м мастере, но чтобы сделать это, необходимо узнать «MASTER_LOG_FILE» и «MASTER_LOG_POS» на 1-м мастере.
Смотрим статус мастера ( я выводил его выше) на 1-й ноде:
# mysql -u root -p -e 'show master status;'
Или:
mysql> show master status;
Вывод:
+------------------+----------+--------------+---------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+---------------------------------------------+ | mysql-bin.000002 | 107 | | information_schema,mysql,performance_schema | +------------------+----------+--------------+---------------------------------------------+ 1 row in set (0.00 sec)
Видим, что «MASTER_LOG_FILE = mysql-bin.000002, а «MASTER_LOG_POS» = 107.
На 2-й ноде выполняем:
mysql> slave stop; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> CHANGE MASTER TO MASTER_HOST = '192.168.13.147', MASTER_USER = 'replica', MASTER_PASSWORD = '%repl2017', MASTER_LOG_FILE = 'mysql-bin.000002', MASTER_LOG_POS = 107; Query OK, 0 rows affected (0.02 sec) mysql> slave start; Query OK, 0 rows affected (0.00 sec) mysql>
Думаю что не стоит объяснять что и где нужно заменить — это интуитивно понятно.
Делаем репликацию на 1-м сервере, но для этого смотрим мастер статус на 2-м:
mysql> SHOW MASTER STATUS; +------------------+----------+--------------+---------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+---------------------------------------------+ | mysql-bin.000002 | 106 | | information_schema,mysql,performance_schema | +------------------+----------+--------------+---------------------------------------------+ 1 row in set (0.00 sec) mysql>
Видим, что «MASTER_LOG_FILE = mysql-bin.000002, а «MASTER_LOG_POS» = 106.
И на 1-м выполняем команду:
mysql> slave stop; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> CHANGE MASTER TO MASTER_HOST = '192.168.13.151', MASTER_USER = 'replica', MASTER_PASSWORD = '%repl2017', MASTER_LOG_FILE = 'mysql-bin.000002', MASTER_LOG_POS = 106; Query OK, 0 rows affected (0.03 sec) mysql> slave start; Query OK, 0 rows affected (0.00 sec) mysql>
После чего, можно посмотреть статус слейва на всех мастерах.
МАСТЕР_1:
mysql> show slave status \G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.13.151 Master_User: replica Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 106 Relay_Log_File: mysql-relay-bin.000002 Relay_Log_Pos: 252 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: information_schema,mysql,performance_schema Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 106 Relay_Log_Space: 408 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: 2 1 row in set (0.00 sec) ERROR: No query specified mysql>
МАСТЕР_2:
mysql> show slave status \G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.13.147 Master_User: replica Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 107 Relay_Log_File: mysql-relay-bin.000002 Relay_Log_Pos: 252 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: information_schema,mysql,performance_schema Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 107 Relay_Log_Space: 407 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: 1 row in set (0.00 sec) ERROR: No query specified mysql>
Если необходимо собрать кластер более чем 2 мастера, то необходимо соединять их постепенно и по цепочке. А сейчас, перейдем к тестированию созданного кластера.
Тестирования репликации master-master в mysql
Потестируем репликацию и убедимся что все хорошо работает.
На 1-м мастере я создам базу данных и таблицу:
mysql> create database master_1; Query OK, 1 row affected (0.00 sec) mysql> create table master_1.flowers (`id` varchar(10)); Query OK, 0 rows affected (0.01 sec) mysql>
На мастере 2 смотрю что получилось:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | master_1 | | mysql | | test | +--------------------+ 4 rows in set (0.00 sec) mysql> show tables in master_1 -> ; +--------------------+ | Tables_in_master_1 | +--------------------+ | flowers | +--------------------+ 1 row in set (0.00 sec) mysql>
Видно что репликация работает и все данные реплицировало на 2-й мастер с 1-го. Переходим тестировать мастер 2, для этого, я создаю на нем же БД и таблицу:
mysql> create database master_2; Query OK, 1 row affected (0.00 sec) mysql> create table master_2.flowers (`id` varchar(10)); Query OK, 0 rows affected (0.00 sec) mysql>
И на 1-м выполняю команду:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | master_1 | | master_2 | | mysql | | performance_schema | +--------------------+ 5 rows in set (0.01 sec) mysql> show tables in master_2; +--------------------+ | Tables_in_master_2 | +--------------------+ | flowers | +--------------------+ 1 row in set (0.00 sec) mysql>
Видим что все работает должным образом и настройка репликации Master-Master на MySQL завершена!
Приветствую!
Спасибо за статью, у Вас во втором конфиге ошибка в комментарии к автоинкременту и отсутствует заголовок [mysqld].