您好,登錄后才能下訂單哦!
異步復制(Asynchronous Replication )
mysql默認的復制就是異步的,主庫在執行完客戶端提交的事物后會立即返回結果給客戶端,并不判斷從庫是否已經接受并處理,這樣就會有一個問題,如果這個時候主庫crash,主庫上已經提交的事物可能還沒有傳到從庫上,如果此時,強行將從提升為主,可能導致新主上的數據丟失。
全同步復制(Fully Synchronous Replication )
指當主庫執行完一個事物,所有的從庫都執行了該事物才返回給客戶端。因為需要等待所有從庫執行完該事物才返回,所以全同步復制對性能影響很嚴重。
半同步復制(Semisynchronous Repalication)
介于異步復制和全同步復制之間,主庫在執行完客戶端提交的事務后不是立刻返回給客戶端,而是等待至少一個從庫接收到并寫到relay log中才返回給客戶端。相對于異步復制,半同步復制提高了數據的安全性,同時它也造成了一定程度的延遲。
分為兩種半同步:
(1)官方半同步
即參數 rpl_semi_sync_master_wait_point = after_commit時
原理:
客戶端發送過來一個請求,經過mysql的SQL分析,存儲引擎處理,寫入binlog,然后再存儲引擎層提交,寫入從庫的relaylog,最后返回給客戶端。
缺點:
(1)在storage commit提交之后,其他會話都可以讀到更新的數據,但是本客戶端還沒有,需要等待從庫接收完日志才能返回結果。
(2)當在storage commit之后,此時如果主crash了,從庫還沒有接收到relaylog,這個時候要進行主從切換,會導致新主數據比原來主數據少,即丟失部分數據。
(2)增強半同步(又稱社區半同步,無損lossless半同步等)
即參數 rpl_semi_sync_master_wait_point = after_sync (參數默認值)
原理:
客戶端發送過來一個請求,經過mysql的SQL分析,存儲引擎處理,寫入binlog,然后寫入從庫的relaylog,存儲引擎層提交,最后返回給客戶端。
優點:
主庫把更新先發送給從庫的relaylog,然后再提交,返回結果給客戶端,這個過程即使在storage commit之后主crash了,日志也已經寫入到relaylog中,從庫和主庫數據一致。
要想使用半同步復制,必須滿足以下幾個條件:
1. MySQL 5.5及以上版本
2. 變量have_dynamic_loading為YES
3. 異步復制已經存在
4.不支持多源復制
1.基本環境
master | slave | |
數據庫版本 | 5.7.16 | 5.7.16 |
IP | 192.168.91.16 | 192.168.91.22 |
serverid | 330616 | 330622 |
端口號 | 3306 | 3306 |
2.主從配置
master:
配置文件中設置:
server-id = 330616
binlog_format = row
log-bin = /data/mysql3306/logs/mysql-bin
skip_slave_start=1
log-slave-updates=0
gtid_mode=ON
enforce-gtid-consistency=ON
slave:
配置文件中設置:
server-id = 330622
binlog_format = row
relay-log=relay-bin
relay-log-index=relay-bin.index
skip_slave_start=1
log_slave_updates=0
gtid_mode=on
enforce-gtid-consistency=on
3.主庫創建用戶
master1:
create user rep@'192.168.91.%' identified by '147258';
grant replication slave on *.* to rep@'192.168.91.%';
4.從庫 change master to
slave:
change master to
master_host='192.168.91.16',
master_port=3306,
master_user='rep',
master_password='147258',
master_auto_position=1;
5.安裝插件
master:
install plugin rpl_semi_sync_master soname 'semisync_master.so';
show plugins;
也可以通過下載配置文件中重啟服務加載插件:
plugin-load=rpl_semi_sync_master=semisync_master.so
slave:
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
show plugins;
也可以通過下載配置文件中重啟服務加載插件:
plugin-load=rpl_semi_sync_slave=semisync_slave.so
6.編輯配置文件
master
#semi
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000 #1 second
動態生效:
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_master_timeout=1000;
slave
#semi
rpl_semi_sync_slave_enabled=1
動態生效:
set global rpl_semi_sync_slave_enabled=1;
在有的高可用架構下,如果需要主從切換繼續使用半同步,主從都需要加載插件并添加配置文件:
#plugins
plugin-load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
#semi
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000 #1 second
rpl_semi_sync_slave_enabled=1
7.參數和狀態
variables:
rpl_semi_sync_master_enabled = ON
表示在master上已經開啟半同步復制模式
rpl_semi_sync_master_timeout = 10000
默認為10000毫秒,等于10秒,這個參數動態可調,表示主庫在某次事務中,如果等待時間超過10秒,那么則降級為異步復制模式,不再等待SLAVE從庫。如果主庫再次探測到,SLAVE從庫恢復了,則會自動再次回到半同步復制模式。
rpl_semi_sync_master_trace_level = 32
用于開啟半同步復制模式時的調試級別,默認是32
rpl_semi_sync_master_wait_for_slave_count=1;
該參數控制主需要等待多少個slave應答,才能返回給客戶端,默認為1。
rpl_semi_sync_master_wait_point = AFTER_SYNC
半同步的方式
status:
Rpl_semi_sync_master_clients
當前半同步復制從的個數,如果是一主多從的架構,并不包含異步復制從的個數。
Rpl_semi_sync_master_yes_tx
表示成功使用半同步的事物
Rpl_semi_sync_master_no_tx
表示沒有使用半同步的事物為:
例:
master:
怎么查看是否開啟半同步:
root@localhost [testdb]> show global variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON | --表示主庫上面的半同步已經開啟
| rpl_semi_sync_master_timeout | 1000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+-------------------------------------------+------------+
測試插入一條數據:
root@localhost [testdb]>insert into t1 values(4,'ddd');
root@localhost [testdb]>show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 1 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 | --表示沒有使用半同步的事物
| Rpl_semi_sync_master_status | ON | --表示半同步正在運行
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 2920 |
| Rpl_semi_sync_master_tx_wait_time | 2920 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 | --表示成功使用半同步的事物
| Rpl_semi_sync_slave_status | OFF |
+--------------------------------------------+-------+
slave:
root@localhost [(none)]>stop slave;
root@localhost [testdb]>show status like '%semi%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | OFF |
+----------------------------+-------+
master:
root@localhost [testdb]>insert into t1 values(5,'eee');
Query OK, 1 row affected (1.01 sec) --這里插入第一條數據用了1.01秒,是由rpl_semi_sync_master_timeout=1000ms控制,因為1秒后超時不使用半同步,變成普通復制。
root@localhost [testdb]>insert into t1 values(6,'fff');
Query OK, 1 row affected (0.00 sec) --后面的操作默認不使用半同步,所以用時比較快。
root@localhost [testdb]>show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 1 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 2 | ----表示沒有使用半同步的事物為2個,如果這個值比較大,那么從庫可能有問題,需要優化。
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 2920 |
| Rpl_semi_sync_master_tx_wait_time | 2920 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
| Rpl_semi_sync_slave_status | OFF |
+--------------------------------------------+-------+
rpl_semi_sync_master_wait_for_slave_count=N;
該參數控制主需要等待多少個slave應答,才能返回給客戶端,默認為1。
例:
root@localhost [testdb]>set global rpl_semi_sync_master_wait_for_slave_count=2;
root@localhost [testdb]>show variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 1000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 2 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
+-------------------------------------------+------------+
root@localhost [testdb]>insert into t2 values(6,'fff');
Query OK, 1 row affected (1.03 sec) --超時之后采用異步復制模式
總結:
1. 在一主多從的架構中,如果要開啟半同步復制,并不要求所有的從都是半同步復制。
2. MySQL 5.7極大的提升了半同步復制的性能。
(1)5.6版本的半同步復制,dump thread 承擔了兩份不同且又十分頻繁的任務:傳送binlog 給slave ,還需要等待slave反饋信息,而且這兩個任務是串行的,dump thread 必須等待 slave 返回之后才會傳送下一個 events 事務。dump thread 已然成為整個半同步提高性能的瓶頸。在高并發業務場景下,這樣的機制會影響數據庫整體的TPS 。
(2)5.7版本的半同步復制中,獨立出一個 ack collector thread ,專門用于接收slave 的反饋信息。這樣master 上有兩個線程獨立工作,可以同時發送binlog 到slave ,和接收slave的反饋。
參考鏈接:
https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。