半同步簡介:
在默認情況下,MySQL的複製是異步的,這意味着主服務器及其從服務器是獨立的。異步複製可以提供最佳的性能,因爲主服務器在將更新的數據寫入它的二進制日誌(Binlog)文件中後,無需等待驗證更新數據是否已經複製到從服務器中,就可以自由處理其它進入的事務處理請求。但這也同時帶來了很高的風險,如果在主服務器或從服務器端發生故障,會造成主從數據的不一致,甚至在恢復時造成數據丟失。
從MySQL5.5開始引入了一種半同步複製功能,該功能可以確保主服務器和訪問鏈中至少一臺從服務器之間的數據一致性和冗餘。在這種配置結構中,一臺主服務器和其許多從服務器都進行了配置,這樣在複製拓撲中,至少有一臺從服務器在父主服務器進行事務處理前,必須確認更新已經收到並寫入了其中繼日誌(Relay Log)。當出現超時,源主服務器必須暫時切換到異步複製模式重新複製,直到至少有一臺設置爲半同步複製模式的從服務器及時收到信息。
繼5.5半同步複製後,MySQL5.6又對其進行了優化和改進,其中有兩個地方較爲重要:
1、在主從切換後,在傳統的方式裏,需要找到binlog和POS點,然後更改master指向,而在mysql5.6裏,你無須再知道binlog和POS點,你只需要知道master的IP、端口,賬號密碼即可,因爲同步複製是自動的,mysql通過內部機制GTID自動找點同步。
2、多線程複製,以前的版本,同步複製是單線程的,只能一個一個執行,在MySQL5.6裏,可以做到多個庫之間的多線程複製,但一個庫裏的表,多線程複製是無效的。
一、試驗環境準備
1.1、安裝平臺:vmware workstation 10
操作系統:CentOS release 6.6 (Final) x86_64,最小化安裝。
MySQL版本:mysql-5.6.24-linux-glibc2.5-x86_64
關閉防火牆
1.2、服務器IP地址規劃:
MySQL Master:192.168.1.152
MySQL Slave1:192.168.1.201
MySQL Slave2:192.168.1.202
1.3、實驗拓撲:
二、安裝Mysql5.6
2.1、由於是最小化安裝的系統,需要安裝一些基本的組建
# yum -y groupinstall "Perl Support" # yum -y instdall vim wget # cd /usr/local/src # wget http://mirrors.sohu.com/mysql/MySQL-5.6/mysql-5.6.24-linux-glibc2.5-x86_64.tar.gz
2.2、新建用戶和數據目錄。
# mkdir -pv /mydata/data # groupadd -r mysql # useradd -g mysql -r -s /sbin/nologin -M -d /mydata/data mysql # chown -R mysql:mysql /mydata/data
2.3、安裝並初始化mysql
# tar zxvf mysql-5.6.24-linux-glibc2.5-x86_64.tar.gz -C /usr/local # cd /usr/local/ # ln -sv mysql-5.6.24-linux-glibc2.5-x86_64 mysql # cd mysql # chown -R mysql:mysql . # scripts/mysql_install_db --user=mysql --datadir=/mydata/data # chown -R root .
2.4、爲mysql提供主配置文件
# cd /usr/local/mysql # cp support-files/my-default.cnf /etc/my.cnf
2.5、爲mysql配置sysv服務腳本
# cd /usr/local/mysql # cp support-files/mysql.server /etc/rc.d/init.d/mysqld # chkconfig --add mysqld //添加至服務列表 # chkconfig mysqld on
爲了使用mysql的安裝符合系統使用規範,並將其開發組件導出給系統使用,這裏還需要進行如下步驟:
2.6、輸出mysql的man手冊至man命令的查找路徑。
編輯/etc/man.config,添加如下行即可
MANPATH /usr/local/mysql/man
2.7、輸出mysql的頭文件至系統頭文件路徑/usr/include
這可以通過簡單的創建鏈接實現
# ln -sv /usr/local/mysql/include /usr/include/mysql
2.8、輸出mysql的庫文件給系統庫查找路徑。
# echo '/usr/local/mysql/lib' > /etc/ld.so.conf.d/mysql.conf # ldconfig //讓系統重新載入系統庫
2.9、修改PATH環境變量,讓系統可以直接使用mysql的相關命令。
# echo "export PATH=$PATH:/usr/local/mysql/bin " >/etc/profile.d/mysql.sh # source /etc/profile.d/mysql.sh
以上安裝過程在三臺服務器軍需執行。
三、主從模式配置
3.1、配置master節點:
[root@master ~]# cat /etc/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 port=3306 datadir=/mydata/data socket=/tmp/mysql.sock report-host=master rpl_semi_sync_master_enabled=ON
配置參數簡要說明:
binlog-format:二進制日誌的格式,有row、statement和mixed三種類型;當設置隔離級別爲READ-COMMITED必須設置二進制日誌格式爲ROW,現在MySQL官方認爲STATEMENT這個已經不再適合繼續使用;mixed類型在默認的事務隔離級別下,可能會導致主從數據不一致; log-bin: 二進制日誌存名,可指定存放路徑; log-slave-updates:slave更新時是否記錄到日誌中; gtid-mode:指定GTID的類型,否則就是普通的複製架構; enforce-gtid-consistency:是否強制GTID的一致性; master-info-repository和relay-log-info-repository:啓用此兩項,可用於實現在崩潰時保證二進制及從服務器安全的功能; binlog-rows-query-log-events:啓用之可用於在二進制日誌詳細記錄事件相關的信息,可降低故障排除的複雜度; server-id:同一個複製拓撲中的所有服務器的id號必須惟一; report-port:產生複製報告時在哪個端口上提供相關功能; report-host:產生複製報告時在哪個主機上提供相關功能,一般爲自己的主機名; sync-master-info:啓用之可確保服務器崩潰時無信息丟失; slave-paralles-workers:設定從服務器啓動幾個SQL複製線程數;0表示關閉多線程複製功能;數字太大也無意義最好與要複製的數據庫的數目相同 binlog-checksum:複製時是否校驗二進制文件的完整性等相關功能;binlog的校驗格式校驗算法(CRC32:循環冗餘校驗碼32位); datadir:數據文件存放路徑; master-verify-checksum:檢驗主服務器二進制日誌的相關功能; slave-sql-verify-checksum:校驗從服務器中繼日誌的相關功能的; rpl_semi_sync_master_enabled:是否開啓半同步複製;
3.2、配置slave節點
[root@slave1 ~]# cat /etc/my.cnf
[mysqld] binlog-format=ROW 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 port=3306 log-bin=mysql-bin.log datadir=/mydata/data socket=/tmp/mysql.sock report-host=slave1 rpl_semi_sync_slave_enabled=ON
[root@slave2 ~]# cat /etc/my.cnf
[mysqld] binlog-format=ROW 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 port=3306 log-bin=mysql-bin.log datadir=/mydata/data socket=/tmp/mysql.sock report-host=slave2 rpl_semi_sync_slave_enabled=ON
3.3、創建複製用戶
在主庫上執行
mysql> GRANT REPLICATION SLAVE ON *.* [email protected] IDENTIFIED BY 'passwd'; mysql> GRANT REPLICATION SLAVE ON *.* [email protected] IDENTIFIED BY 'passwd'; mysql> FLUSH PRIVILEGES;
3.4、在主從節點上安裝相關的插件並啓動複製
在主庫上執行
master> INSTALL PLUGINrpl_semi_sync_master SONAME 'semisync_master.so';
在從庫上執行
slave> INSTALL PLUGINrpl_semi_sync_slave SONAME 'semisync_slave.so';
安裝完畢後在兩從庫上定義到主庫的複製連接
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.152',MASTER_USER='slave', MASTER_PASSWORD='passwd', MASTER_AUTO_POSITION=1; mysql> START SLAVE; mysql> show global variables like'%gtid%';
可以看到主從服務器已經啓用gtid功能。
在主庫上查看已連接的slave主機
mysql> show slave hosts; +-----------+--------+------+-----------+--------------------------------------+ | Server_id | Host | Port | Master_id | Slave_UUID | +-----------+--------+------+-----------+--------------------------------------+ | 11 | slave1 | 3306 | 1 | 9cb0c60a-9676-11e4-9d56-000c2989857d | | 12 | slave2 | 3306 | 1 | 485767ea-9676-11e4-9d54-005056291b33 | +-----------+--------+------+-----------+--------------------------------------+ 2 rows in set (0.00 sec)
查看slave1的複製狀態
再去查看slave2的狀態
mysql> show slave status\G;
可以看到此時兩個從庫的複製進度是一樣的。
3.5、在主庫寫入數據進行測試
mysql> create database just_for_test; Query OK, 1 row affected (0.15 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | just_for_test | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.01 sec)
在從庫上執行查詢可以看到
slave1> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | just_for_test | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.03 sec) slave1> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.1.152 Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000002 Read_Master_Log_Pos: 360 Relay_Log_File: slave1-relay-bin.000005 Relay_Log_Pos: 572 Relay_Master_Log_File: master-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes 從庫2 slave2> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | just_for_test | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.11 sec) slave2> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.1.152 Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000002 Read_Master_Log_Pos: 360 Relay_Log_File: slave2-relay-bin.000003 Relay_Log_Pos: 572 Relay_Master_Log_File: master-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes
四、配置基於ssl的加密
4.1、主服務器上生成私鑰
# mkdir /usr/local/mysql/ssl # cd /usr/local/mysql/ssl # umask 077 openssl genrsa 2048 > ca-key.pem # openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca-cert.pem
4.2、主服務器上生成自簽證書
# openssl req -newkey rsa:2048 -days 3650 -nodes -keyout master-key.pem -out master-req.pem # openssl rsa -in master-key.pem -out master-key.pem # openssl x509 -req -in master-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out master-cert.pem
權限設置
# chown mysql.mysql -R * # chmod 600 *
4.3、爲從服務器生成證書
# openssl req -newkey rsa:2048 -days 3650 -nodes -keyout slave-key.pem -out slave-req.pem # openssl x509 -req -in slave-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out slave-cert.pem
將CA證書、簽署的slave端證書、master證書及私鑰傳送到slave服務器上
# scp ca-cert.pem slave-key.pem slave-cert.pem master-cert.pem master-key.pem 192.168.1.201:/usr/local/mysql/ssl/ # scp ca-cert.pem slave-key.pem slave-cert.pem master-cert.pem master-key.pem 192.168.1.202:/usr/local/mysql/ssl/
4.4、配置主從ssl
編輯master服務器my.cnf配置文件
# vim /etc/my.cnf //添加內容如下 ssl ssl-ca = /usr/local/mysql/ssl/ca-cert.pem ssl-cert = /usr/local/mysql/ssl/master-cert.pem ssl-key = /usr/local/mysql/ssl/master-key.pem //更改證書屬主屬組 # chown mysql.mysql -R /usr/local/mysql/ssl # chmod 600 * /usr/local/mysql/ssl //重啓mysql服務 # service mysqld restart //在主服務器上創建ssl連接用戶 mysql> grant replication client,replication slave on*.* to "ssl"@"192.168.1.201" identified by 'mysql'; mysql> grant replication client,replication slave on*.* to "ssl"@"192.168.1.202" identified by 'mysql'; mysql> flush privileges;
配置從服務器ssl(該步驟兩臺從服務器相同)
# mkdir /usr/local/mysql/ssl
編輯slave服務器my.cnf配置文件
# vim /etc/my.cnf //添加內容如下 ssl ssl-ca = /usr/local/mysql/ssl/ca-cert.pem ssl-cert = /usr/local/mysql/ssl/slave-cert.pem ssl-key = /usr/local/mysql/ssl/slave-key.pem //重啓mysql服務 # service mysqld restart
啓動從服務器上的複製
mysql > stop slave; mysql > change master to master_host='192.168.1.152', master_user='ssl',master_password='mysql',MASTER_AUTO_POSITION=1,master_ssl=1,master_ssl_ca='/usr/local/mysql/ssl/ca-cert.pem',master_ssl_cert='/usr/local/mysql/ssl/master-cert.pem',master_ssl_key='/usr/local/mysql/ssl/master-key.pem'; mysql> start slave; mysql> show slave status \G
可以看到如下信息
mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.1.152 Master_User: ssl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000003 Read_Master_Log_Pos: 872 Relay_Log_File: slave2-relay-bin.000002 Relay_Log_Pos: 411 Relay_Master_Log_File: master-bin.000003 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: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 872 Relay_Log_Space: 616 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: Yes Master_SSL_CA_File: /usr/local/mysql/ssl/ca-cert.pem Master_SSL_CA_Path: Master_SSL_Cert: /usr/local/mysql/ssl/master-cert.pem Master_SSL_Cipher: Master_SSL_Key: /usr/local/mysql/ssl/master-key.pem 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: 1 Master_UUID: 963e99b9-9674-11e4-9d49-000c297410f1 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 the slave I/O thread to update it 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: 963e99b9-9674-11e4-9d49-000c297410f1:1-6 Auto_Position: 1
但是到這裏之後發現了一個問題,那就是我使用的編譯好的mysql二進制包不支持ssl,要想支持需要重新編譯mysql,限於時間有限,這裏就不重來了,有需要的朋友就自己折騰下吧。