使用Docker快速體驗MySQL半同步複製機制
近期研究了下SQL/">MySQL的半同步複製機制(可參考《ofollow,noindex">使用MySQL半同步複製保障關鍵資料可靠性和一致性 》),想要體驗一下。搭建環境是件麻煩事,然後就想到用Docker快速搭建環境。
1. MySQL Image的選取
MySQL官方提供了標準Image,能夠滿足基本的MySQL功能。假如本地沒有這個Image,可以通過以下命令獲取。
docker pull mysql
預設拉取的是latest版本,也可指定具體版本,如:
docker pull mysql:5.7
但需要注意的是,半同步複製是從5.5版本開始支援的,所以最低需要5.5版本。
2. 搭建一主兩備DB
2.1 配置DB
MySQL官方Image提供的my.cnf只包含基本配置,假如有自己定製的DB配置,可以放到/etc/mysql/conf.d目錄下,這個目錄下字尾為.cnf檔案內的配置,會補充和覆蓋my.cnf中的配置。一種最簡單的方法是使用volume機制,將本地的配置掛載到container中,這樣既方便本地修改,也可以在建立container時就包含定製配置。
在本地建立相應目錄:
mkdir -p master/conf slave1/conf slave2/conf
編輯Master DB的補充配置,vi master/conf/my.cnf,內容如下:
[mysqld] binlog-format=ROW log-bin=master-bin log-slave-updates=true gtid-mode=on enforce-gtid-consistency=true master-info-repository=TABLE relay-log-info-repository=TABLE sync-master-info=1 slave-parallel-workers=2 binlog-checksum=CRC32 master-verify-checksum=1 slave-sql-verify-checksum=1 binlog-rows-query-log_events=1 server-id=1 report-port=3306 report-host=master plugin_load="rpl_semi_sync_master=semisync_master.so" rpl_semi_sync_master_enabled=1 rpl_semi_sync_master_timeout=1000
說明:使用MySQL的複製功能需要開啟binlog。半同步複製可以在啟動DB後安裝semisync_master.so,這裡在配置檔案中加上,啟動DB時自動載入。rpl_semi_sync_master_enabled=1啟用半同步複製的主DB角色功能。體驗時設定半同步複製超時時間rpl_semi_sync_master_timeout為1秒。
編輯Slave DB 1的補充配置,vi slave1/conf/my.cnf,內容如下:
[mysqld] binlog-format=ROW log-bin=mysql-bin.log log-slave-updates=true gtid-mode=on enforce-gtid-consistency=true master-info-repository=TABLE relay-log-info-repository=TABLE sync-master-info=1 slave-parallel-workers=2 binlog-checksum=CRC32 master-verify-checksum=1 slave-sql-verify-checksum=1 binlog-rows-query-log_events=1 server-id=11 report-port=3306 report-host=slave1 plugin_load="rpl_semi_sync_slave=semisync_slave.so" rpl_semi_sync_slave_enabled=1
說明:與主DB類似,開啟binlog,啟動DB時自動載入semisync_slave.so,並通過rpl_semi_sync_slave_enabled=1啟用半同步複製的備DB角色功能。超時時間由Master設定,Slave不需要設定。
編輯Slave DB 2的補充配置,vi slave2/conf/my.cnf,內容如下:
[mysqld] binlog-format=ROW log-bin=mysql-bin.log log-slave-updates=true gtid-mode=on enforce-gtid-consistency=true master-info-repository=TABLE relay-log-info-repository=TABLE sync-master-info=1 slave-parallel-workers=2 binlog-checksum=CRC32 master-verify-checksum=1 slave-sql-verify-checksum=1 binlog-rows-query-log_events=1 server-id=12 report-port=3306 report-host=slave2 plugin_load="rpl_semi_sync_slave=semisync_slave.so" rpl_semi_sync_slave_enabled=1
與Slave 1類似,需要注意的是server-id不能重複。
2.2 啟動DB container
執行一下命令,建立三個DB container,並掛載相應的補充配置檔案。這裡指定了埠對映,方便登陸DB操作。
docker run --name master -p 53306:3306 -v /data/test/master/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql docker run --name slave1 -p 53307:3306 -v /data/test/slave1/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql docker run --name slave2 -p 53308:3306 -v /data/test/slave2/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql
2.3 配置主從關係
首先獲取3個container的內部IP,執行下面命令:
$ docker inspect --format '{{.NetworkSettings.IPAddress}}' master slave1 slave2 172.17.0.100 172.17.0.101 172.17.0.102
登陸Master DB授權:
$ mysql -h127.0.0.1 -uroot -p123456 -P53306 > GRANT REPLICATION SLAVE ON *.* TO slave@172.17.0.101 IDENTIFIED BY '123456'; > GRANT REPLICATION SLAVE ON *.* TO slave@172.17.0.102 IDENTIFIED BY '123456'; > FLUSH PRIVILEGES;
分別登陸Slave DB 1和Slave DB 2配置主從關係:
$ mysql -h127.0.0.1 -uroot -p123456 -P53307 > CHANGE MASTER TO MASTER_HOST='172.17.0.100',MASTER_USER='slave',MASTER_PASSWORD='123456', MASTER_AUTO_POSITION=1; > START SLAVE;
$ mysql -h127.0.0.1 -uroot -p123456 -P53308 > CHANGE MASTER TO MASTER_HOST='172.17.0.100',MASTER_USER='slave',MASTER_PASSWORD='123456', MASTER_AUTO_POSITION=1; > START SLAVE;
至此,一主兩備DB已經搭建好了,可以通過下面命令檢視同步狀態。
$ mysql -h127.0.0.1 -uroot -p123456 -P53306 > show slave hosts; $ mysql -h127.0.0.1 -uroot -p123456 -P53307 > show slave hosts; $ mysql -h127.0.0.1 -uroot -p123456 -P53308 > show slave hosts;
3. 體驗半同步複製功能
3.1 正常情況
在Master DB建立test庫t1表,並寫入一條記錄,操作都是立即返回成功。檢查Slave DB 1和Slave DB 2,發現數據已經成功同步。
3.2 Slave DB 1掛了
停止Slave DB 1的container:
docker stop slave1
在Master DB寫入一條記錄,操作也是立即返回成功。檢查Slave DB 2,發現數據已經成功同步。
3.3 兩臺Slave DB都掛了
再停止Slave DB 2的container:
docker stop slave2
在Master DB寫入一條記錄,操作需要等待1秒才返回成功;再寫入一條記錄,立即返回成功。等待1秒對應半同步複製的超時時間,超時時間內兩臺Slave DB都沒有響應,Master DB自動切換成非同步複製模式,後面再次寫入記錄就不需要等待了。