讓咱們繼續 MySQL 集羣搭建之旅,大部分 MySQL 的集羣都是採用主主從的經典模式,這也是部署高可用集羣的基礎。從上文咱們已經知道若是搭建 MySQL 的主備模式,若是沒看過的能夠了解一下。mysql
上次咱們搭建了主備架構,以下所示sql
此次咱們的搭建目標是數據庫
具體配置信息segmentfault
IP | 系統 | 端口 | MySQL版本 | 節點 | 讀寫 | 說明 |
---|---|---|---|---|---|---|
192.168.41.83 | Centos6.8 | 3306 | 5.7.20 | Master | 讀寫 | 主節點 |
192.168.41.72 | Centos6.8 | 3306 | 5.7.20 | Standby | 只讀,可切換爲讀寫 | 備節點,容許升級爲主節點 |
192.168.41.83 | Centos6.8 | 3307 | 5.7.20 | Slave | 只讀 | 從節點 |
環境我已經準備好了, 以下圖所示,若是不知道如何安裝 MySQL 和搭建主備能夠參考之前的文章服務器
參考配置架構
Mastersocket
[client] port = 3306 default-character-set=utf8mb4 socket = /data/mysql_db/mysql_seg_3306/mysql.sock [mysqld] datadir = /data/mysql_db/mysql_seg_3306 basedir = /usr/local/mysql57 tmpdir = /tmp socket = /data/mysql_db/mysql_seg_3306/mysql.sock pid-file = /data/mysql_db/mysql_seg_3306/mysql.pid skip-external-locking = 1 skip-name-resolve = 1 port = 3306 server_id = 833306 default-storage-engine = InnoDB character-set-server = utf8mb4 default_password_lifetime=0 auto_increment_offset = 1 auto_increment_increment = 2 #### log #### log_timestamps=system log_bin = /data/mysql_log/mysql_seg_3306/mysql-bin log_bin_index = /data/mysql_log/mysql_seg_3306/mysql-bin.index binlog_format = row relay_log_recovery=ON relay_log=/data/mysql_log/mysql_seg_3306/mysql-relay-bin relay_log_index=/data/mysql_log/mysql_seg_3306/mysql-relay-bin.index log_error = /data/mysql_log/mysql_seg_3306/mysql-error.log #### replication #### log_slave_updates = 1 replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.% #### semi sync replication settings ##### plugin_dir=/usr/local/mysql57/lib/plugin plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so" loose_rpl_semi_sync_master_enabled = 1 loose_rpl_semi_sync_slave_enabled = 1 loose_rpl_semi_sync_master_timeout = 5000
Standby測試
[client] port = 3306 default-character-set=utf8mb4 socket = /data/mysql_db/mysql_seg_3306/mysql.sock [mysqld] datadir = /data/mysql_db/mysql_seg_3306 basedir = /usr/local/mysql57 tmpdir = /tmp socket = /data/mysql_db/mysql_seg_3306/mysql.sock pid-file = /data/mysql_db/mysql_seg_3306/mysql.pid skip-external-locking = 1 skip-name-resolve = 1 port = 3306 server_id = 723306 default-storage-engine = InnoDB character-set-server = utf8mb4 default_password_lifetime=0 auto_increment_offset = 2 auto_increment_increment = 2 #### log #### log_timestamps=system log_bin = /data/mysql_log/mysql_seg_3306/mysql-bin log_bin_index = /data/mysql_log/mysql_seg_3306/mysql-bin.index binlog_format = row relay_log_recovery=ON relay_log=/data/mysql_log/mysql_seg_3306/mysql-relay-bin relay_log_index=/data/mysql_log/mysql_seg_3306/mysql-relay-bin.index log_error = /data/mysql_log/mysql_seg_3306/mysql-error.log #### replication #### log_slave_updates = 1 replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.% #### semi sync replication settings ##### plugin_dir=/usr/local/mysql57/lib/plugin plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so" loose_rpl_semi_sync_master_enabled = 1 loose_rpl_semi_sync_slave_enabled = 1 loose_rpl_semi_sync_master_timeout = 5000
Slavespa
[client] port = 3307 default-character-set=utf8mb4 socket = /data/mysql_db/mysql_seg_3307/mysql.sock [mysqld] datadir = /data/mysql_db/mysql_seg_3307 basedir = /usr/local/mysql57 tmpdir = /tmp socket = /data/mysql_db/mysql_seg_3307/mysql.sock pid-file = /data/mysql_db/mysql_seg_3307/mysql.pid skip-external-locking = 1 skip-name-resolve = 1 port = 3307 server_id = 833307 read_only=1 default-storage-engine = InnoDB character-set-server = utf8mb4 default_password_lifetime=0 #### log #### log_timestamps=system log_bin = /data/mysql_log/mysql_seg_3307/mysql-bin log_bin_index = /data/mysql_log/mysql_seg_3307/mysql-bin.index binlog_format = row relay_log_recovery=ON relay_log=/data/mysql_log/mysql_seg_3307/mysql-relay-bin relay_log_index=/data/mysql_log/mysql_seg_3307/mysql-relay-bin.index log_error = /data/mysql_log/mysql_seg_3307/mysql-error.log #### replication #### replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.% #### semi sync replication settings ##### plugin_dir=/usr/local/mysql57/lib/plugin plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so" loose_rpl_semi_sync_master_enabled = 1 loose_rpl_semi_sync_slave_enabled = 1 loose_rpl_semi_sync_master_timeout = 5000
配置解釋日誌
auto_increment_offset
自增字段起始值,設置爲 2 表示自增字段從 2 開始算auto_increment_increment
自增字段步增數值,設置爲 2 表示每次遞增 2,根據主節點設置,自增字段的值多是這樣的: 1,3,5,7...log_slave_updates
將複製事件寫入 binlog, 一臺服務器既作主庫又作從庫此選項必需要開啓, 這裏在 Master 和 Standby 開啓說明一下,設置 auto_increment_offset
, auto_increment_increment
是爲了防止兩個節點雙寫時出現主鍵衝突
如今環境已經準備好了,當前部署狀態爲,Standby 向 Master 同步,Slave 空跑, 如今開始搭建雙主架構
要實現 Master 向 Slave 同步,說簡單點就是反着搭建主備同步。咱們先去備節點記錄當前二進制日誌狀態
db72-3306>>show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000005 | 154 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
正常狀況下,主節點一直有數據寫入,而咱們又設置了 log_slave_updates
,有同窗會疑惑,在咱們記錄當前二進制位置後,若是有數據同步過來,二進制位置變化了,而咱們從舊數據開始同步,會不會發生數據衝突。其實不會,雙主模式下,數據庫會幫咱們處理這種狀況,如今咱們模擬這種狀況,在主節點插入一些數據
db83-3306>>insert into test1 values (0, 'echoQMC', 24); Query OK, 1 row affected (0.01 sec) db83-3306>>select * from test1; +----+---------+-----+ | id | name | age | +----+---------+-----+ | 1 | a | 16 | | 2 | b | 17 | | 3 | c | 18 | | 4 | d | 19 | | 5 | chengqm | 24 | | 7 | echoQMC | 24 | +----+---------+-----+ 6 rows in set (0.00 sec)
插入數據後,咱們再看 Standby 二進制位置
db72-3306>>show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000005 | 424 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
根據咱們第一次獲取到的二進制日誌位置,在 Master 節點執行如下命令即可以開啓同步
-- 重置複製 -- reset slave; -- 同步配置 CHANGE MASTER TO MASTER_HOST='192.168.41.72', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='repl', MASTER_LOG_FILE='mysql-bin.000005', MASTER_LOG_POS=154; -- 開啓同步 start slave
具體執行過程以下
db83-3306>>CHANGE MASTER TO -> MASTER_HOST='192.168.41.72', -> MASTER_PORT=3306, -> MASTER_USER='repl', -> MASTER_PASSWORD='repl', -> MASTER_LOG_FILE='mysql-bin.000005', -> MASTER_LOG_POS=154; Query OK, 0 rows affected, 2 warnings (0.00 sec) db83-3306>>start slave; Query OK, 0 rows affected (0.00 sec)
查看同步狀態
db83-3306>>show slave status \G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.41.72 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000005 Read_Master_Log_Pos: 424 Relay_Log_File: mysql-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000005 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: information_schema.%,performance_schema.%,sys.% Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 424 Relay_Log_Space: 527 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: 723306 Master_UUID: f9610603-e99f-11e8-b980-90b11c1a653a Master_Info_File: /data/mysql_db/mysql_seg_3306/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: Master_TLS_Version: 1 row in set (0.00 sec) ERROR: No query specified
能夠發現同步正常,沒有數據衝突的狀況,如今測試一下在 Standby 寫數據會不會同步到 Master
db72-3306>>insert into test1 values (0, 'Keeming', 24); Query OK, 1 row affected (0.04 sec)
在 Master 節點查看數據
db83-3306>>select * from test1; +----+---------+-----+ | id | name | age | +----+---------+-----+ | 1 | a | 16 | | 2 | b | 17 | | 3 | c | 18 | | 4 | d | 19 | | 5 | chengqm | 24 | | 7 | echoQMC | 24 | | 8 | Keeming | 24 | +----+---------+-----+ 7 rows in set (0.00 sec)
數據被同步過來,雙主架構已經搭建成功,當前架構以下
仔細觀察主鍵的遞增狀況,咱們發如今 Master 節點插入 echoQMC 這條數據,主鍵從 5 跳到 7,在 Standby 節點插入 Keeming 這條數據,主鍵從 7 跳到 8,說明主鍵遞增是不同的,在 Master 插入數據只會有單數主鍵, 在 Standby 插入數據只會有雙數主鍵,這樣即便同時在兩個節點寫數據,也不會有衝突
主主架構已經搭建成功,如今咱們再增長一個 Slave 節點,向 Master 同步,這個過程就是簡單的主備搭建,具體過程就不贅述了。
在使用主主從架構下,爲了數據一致性,咱們通常只容許一個節點有寫操做,其餘節點都設爲只讀,因此在 Slave 配置文件裏面加上了 read_only
, Standby 節點手動設置只讀(方便切換)
全部操做完成後,架構以下
到此,主主備架構搭建完成