MySQL 5.7多源復(fù)制實踐
日期:2017-06-22 10:35:30 / 點(diǎn)擊: 1777
MySQL 5.7發(fā)布后,在復(fù)制方面有了很大的改進(jìn)和提升。比如開始支持多源復(fù)制 (multi-source) 以及真正的支持多線程復(fù)制了。多源復(fù)制可以使用基于二進(jìn)制日志的復(fù)制或者基于事務(wù)的復(fù)制。下面我們講講如何配置基于二進(jìn)制日志的多源復(fù)制。
什么是多源復(fù)制
首先,我們需要清楚幾種常見的復(fù)制模式:
1)一主一從
2)一主多從
3)級聯(lián)復(fù)制
4)multi-master
MySQL 5.7 之前只能實現(xiàn)一主一從、一主多從或者多主多從的復(fù)制。如果想實現(xiàn)多主一從的復(fù)制,只能使用 MariaDB,但是 MariaDB 又與官方的 MySQL 版本不兼容。
MySQL 5.7 開始支持了多主一從的復(fù)制方式,也就是多源復(fù)制。MySQL 5.7 版本相比之前的版本,無論在功能還是性能、安全等方面都已經(jīng)有不少的提升。
首先,我們需要清楚 multi-master
與 multi-source
復(fù)制不是一樣的。multi-master
復(fù)制通常是環(huán)形復(fù)制,你可以在任意主機(jī)上將數(shù)據(jù)復(fù)制給其他主機(jī)。
multi-source
是不同的。簡單的說,多源復(fù)制就是將多個主庫同步到一個從庫上面,從而增加從的利用率,節(jié)省了機(jī)器。如下圖:
多源復(fù)制使用場景
-
數(shù)據(jù)分析部門會需要各個業(yè)務(wù)部門的部分?jǐn)?shù)據(jù)做數(shù)據(jù)分析,這個時候就可以用到多源復(fù)制把各個主數(shù)據(jù)庫的數(shù)據(jù)復(fù)制到統(tǒng)一的數(shù)據(jù)庫中。
-
在從服務(wù)器進(jìn)行數(shù)據(jù)匯總,如果我們的主服務(wù)器進(jìn)行了分庫分表的操作,為了實現(xiàn)后期的一些數(shù)據(jù)統(tǒng)計功能,往往需要把數(shù)據(jù)匯總在一起再統(tǒng)計。
-
在從服務(wù)器對所有主服務(wù)器的數(shù)據(jù)進(jìn)行備份,在MySQL 5.7之前每一個主服務(wù)器都需要一個從服務(wù)器,這樣很容易造成資源浪費(fèi),同時也加大了DBA的維護(hù)成本,但MySQL 5.7引入多源復(fù)制,可以把多個主服務(wù)器的數(shù)據(jù)同步到一個從服務(wù)器進(jìn)行備份。
使用多源復(fù)制的必要條件
不管是使用基于二進(jìn)制日志的復(fù)制或者基于事務(wù)的復(fù)制,要開啟多源復(fù)制功能必須需要在從庫上設(shè)置 master-info-repository
和 relay-log-info-repository
這兩個參數(shù)。
這兩個參數(shù)是用來存儲同步信息的,可以設(shè)置的值為 FILE
和 TABLE
,默認(rèn)值是 FILE
。比如 master-info
就保存在 master.info
文件中, relay-log-info
保存在 relay-log.info
文件中,如果服務(wù)器意外關(guān)閉,正確的 relay-log-info
沒有來得及更新到 relay-log.info
文件,這樣會造成數(shù)據(jù)丟失。
為了數(shù)據(jù)更加安全,通常設(shè)為 TABLE
。這些表都是 innodb
類型的,支持事務(wù)。相對文件存儲安全得多。在 MySQL 庫下可以看見這兩個表信息,分別是 mysql.slave_master_info
和 mysql.slave_relay_log_info
。
這兩個參數(shù)也是可以動態(tài)調(diào)整的。
SET GLOBAL master_info_repository = 'TABLE';
SET GLOBAL relay_log_info_repository = 'TABLE';
如果要啟用 enhanced multi-threaded slave
(多線程復(fù)制),可以設(shè)置以下參數(shù)
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=8
relay_log_recovery=ON
如果SLAVE已經(jīng)為開啟狀態(tài),那么需要首先關(guān)閉SLAVE(STOP SLAVE;)。
配置多源復(fù)制
環(huán)境準(zhǔn)備
這里一共使用了三臺機(jī)器,MySQL版本都為5.7.18。
機(jī)器名 | IP地址 | MySQL角色 |
---|---|---|
dev-master-01 | 192.168.2.210 | MySQL 主庫 |
dev-node-01 | 192.168.2.211 | MySQL 主庫 |
dev-node-02 | 192.168.2.212 | MySQL 從庫 |
安裝MySQL
MySQL安裝比較簡單,官方都有提供不同系統(tǒng)的相應(yīng)軟件源。這里以 Ubuntu 16.04 系統(tǒng)為例:
-
從MySQL官方網(wǎng)站下載APT源
$ wget https://dev.mysql.com/get/mysql-apt-config_0.8.6-1_all.deb
更多軟件源可參考:http://dev.mysql.com/downloads/repo/apt/
,如果是 CentOS/RHEL
系統(tǒng)可參考官方文檔:https://dev.mysql.com/doc/refman/5.7/en/linux-installation-yum-repo.html
-
安裝MySQL軟件源并更新
$ dpkg -i mysql-apt-config_0.8.6-1_all.deb
$ apt-get update
-
安裝MySQL Server和MySQL Client
$ apt-get install mysql-server mysql-client
-
啟動MySQL Server
$ service mysql start
-
檢查MySQL Server是否成功啟動
$ service mysql status
● mysql.service - MySQL Community Server
Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2017-06-12 17:16:09 CST; 32s ago
Process: 10442 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid (code=exited, status=0/SUCCESS)
Process: 10399 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
Main PID: 10446 (mysqld)
Tasks: 27
Memory: 190.8M
CPU: 362ms
CGroup: /system.slice/mysql.service
└─10446 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
配置MySQL多源復(fù)制
-
修改MySQL主配置文件
配置 MySQL 多源復(fù)制,主要是需要在 MySQL 從服務(wù)器的主配置文件 [mysqld]
段中添加以下兩行:
$ vim /etc/mysql/mysql.conf.d/mysqld.cnf
master-info-repository = table
relay-log-info-repository = table
MySQL主服務(wù)器配置片斷
以 dev-master-01
為例,另一臺 Master 也是類似的配置方法。
$ vim /etc/mysql/mysql.conf.d/mysqld.cnf
server-id = 1
log-bin = /var/log/mysql/mysql-bin
log_bin_index = /var/log/mysql/mysql-bin.index
expire_logs_days = 30
max_binlog_size = 100M
binlog_format = ROW
MySQL從服務(wù)器配置片斷
$ vim /etc/mysql/mysql.conf.d/mysqld.cnf
server-id = 3
log-slave-updates = true
skip-slave-start = true
expire_logs_days = 30
max_binlog_size = 100M
log-bin = /var/log/mysql/mysql-bin
relay-log = /var/log/mysql/relay-log
relay-log-index = /var/log/mysql/relay-log-index
relay-log-info-file = /var/log/mysql/relay-log.info
master-info-repository = table
relay-log-info-repository = table
report-port = 3306
report-host = 192.168.2.212
replicate-do-db = master1
replicate-do-db = master2
replicate_wild_do_table=master1.%
replicate_wild_do_table=master2.%
注:server-id
每臺必須配置為不一樣,比如 dev-master-01
為1,dev-node-01
為2,dev-node-02
為3。這里沒有給出全部配置,其它請根據(jù)實際情況自行配置。
-
重啟MySQL服務(wù)器
$ service mysql restart
-
創(chuàng)建具有復(fù)制權(quán)限的用戶
在兩臺 MySQL Master 上創(chuàng)建
mysql> grant replication slave on *.* to 'repl'@'192.168.2.%' identified by '000000';
mysql> flush privileges;
-
從庫分別連接至兩個主庫
MySQL 5.7 有了通信渠道的概念,每一個通信渠道都是一個從服務(wù)器到主服務(wù)器獲得二進(jìn)制日志的鏈接。這意味著每個通信渠道都得有一個 IO_THREAD
。對于每一個主服務(wù)器,我們需要運(yùn)行不同的 CHANGE MASTER
命令和FOR CHANNEL
這個參數(shù)來分別提供不同通信鏈接名字。
下面開始設(shè)置需要同步的源,同步兩個主服務(wù)器的數(shù)據(jù)到從服務(wù)器上。
設(shè)置同步源到 Master1 (在 MySQL 從服務(wù)器上執(zhí)行)
mysql> CHANGE MASTER TO MASTER_HOST='192.168.2.210',
MASTER_USER='repl',
MASTER_PORT=3306,
MASTER_PASSWORD='000000',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=1 FOR CHANNEL 'master1';
設(shè)置同步源到 Master2 (在 MySQL 從服務(wù)器上執(zhí)行)
mysql> CHANGE MASTER TO MASTER_HOST='192.168.2.211',
MASTER_USER='repl',
MASTER_PORT=3306,
MASTER_PASSWORD='000000',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=1 FOR CHANNEL 'master2';
啟動所有SLAVE
mysql> START SLAVE;
也可以單獨(dú)啟動需要同步的通道。
mysql> START SLAVE FOR CHANNEL 'master1';
mysql> START SLAVE FOR CHANNEL 'master2';
停止和 RESET 復(fù)制的命令也同 START 類似,可以操作所有的,也可以操作單個通道。
查看SLAVE信息
mysql> SHOW SLAVE STATUS\\\\G
...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...
確認(rèn) Slave_IO_Running
和 Slave_SQL_Running
兩個參數(shù)都為 Yes 狀態(tài)。
如果要查看單一信道的復(fù)制的詳細(xì)狀態(tài),可以使用以下命令:
mysql> SHOW SLAVE STATUS FOR CHANNEL 'master1'\\\\G;
測試多源復(fù)制
-
在主庫(dev-master-01)實例創(chuàng)建一些數(shù)據(jù)。
mysql> create database master1;
mysql> use master1;
mysql> CREATE TABLE `test1` (`id` int(11) DEFAULT NULL,`count` int(11) DEFAULT NULL);
mysql> insert into test1 values(1,1);