異步復制(Asynchronous Replication )
創(chuàng)新互聯(lián)公司主要為客戶提供服務項目涵蓋了網(wǎng)頁視覺設計、VI標志設計、網(wǎng)絡營銷推廣、網(wǎng)站程序開發(fā)、HTML5響應式成都網(wǎng)站建設、手機網(wǎng)站開發(fā)、微商城、網(wǎng)站托管及成都網(wǎng)站維護、WEB系統(tǒng)開發(fā)、域名注冊、國內(nèi)外服務器租用、視頻、平面設計、SEO優(yōu)化排名。設計、前端、后端三個建站步驟的完善服務體系。一人跟蹤測試的建站服務標準。已經(jīng)為純水機行業(yè)客戶提供了網(wǎng)站制作服務。
MySQL默認的復制就是異步的,主庫在執(zhí)行完客戶端提交的事物后會立即返回結(jié)果給客戶端,并不判斷從庫是否已經(jīng)接受并處理,這樣就會有一個問題,如果這個時候主庫crash,主庫上已經(jīng)提交的事物可能還沒有傳到從庫上,如果此時,強行將從提升為主,可能導致新主上的數(shù)據(jù)丟失。
全同步復制(Fully Synchronous Replication )
指當主庫執(zhí)行完一個事物,所有的從庫都執(zhí)行了該事物才返回給客戶端。因為需要等待所有從庫執(zhí)行完該事物才返回,所以全同步復制對性能影響很嚴重。
半同步復制(Semisynchronous Repalication)
介于異步復制和全同步復制之間,主庫在執(zhí)行完客戶端提交的事務后不是立刻返回給客戶端,而是等待至少一個從庫接收到并寫到relay log中才返回給客戶端。相對于異步復制,半同步復制提高了數(shù)據(jù)的安全性,同時它也造成了一定程度的延遲。
分為兩種半同步:
(1)官方半同步
即參數(shù) rpl_semi_sync_master_wait_point = after_commit時
原理:
客戶端發(fā)送過來一個請求,經(jīng)過mysql的SQL分析,存儲引擎處理,寫入binlog,然后再存儲引擎層提交,寫入從庫的relaylog,最后返回給客戶端。
缺點:
(1)在storage commit提交之后,其他會話都可以讀到更新的數(shù)據(jù),但是本客戶端還沒有,需要等待從庫接收完日志才能返回結(jié)果。
(2)當在storage commit之后,此時如果主crash了,從庫還沒有接收到relaylog,這個時候要進行主從切換,會導致新主數(shù)據(jù)比原來主數(shù)據(jù)少,即丟失部分數(shù)據(jù)。
(2)增強半同步(又稱社區(qū)半同步,無損lossless半同步等)
即參數(shù) rpl_semi_sync_master_wait_point = after_sync (參數(shù)默認值)
原理:
客戶端發(fā)送過來一個請求,經(jīng)過mysql的SQL分析,存儲引擎處理,寫入binlog,然后寫入從庫的relaylog,存儲引擎層提交,最后返回給客戶端。
優(yōu)點:
主庫把更新先發(fā)送給從庫的relaylog,然后再提交,返回結(jié)果給客戶端,這個過程即使在storage commit之后主crash了,日志也已經(jīng)寫入到relaylog中,從庫和主庫數(shù)據(jù)一致。
要想使用半同步復制,必須滿足以下幾個條件:
1. MySQL 5.5及以上版本
2. 變量have_dynamic_loading為YES
3. 異步復制已經(jīng)存在
4.不支持多源復制
1.基本環(huán)境
master | slave | |
數(shù)據(jù)庫版本 | 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.主庫創(chuàng)建用戶
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
動態(tài)生效:
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_master_timeout=1000;
slave
#semi
rpl_semi_sync_slave_enabled=1
動態(tài)生效:
set global rpl_semi_sync_slave_enabled=1;
在有的高可用架構(gòu)下,如果需要主從切換繼續(xù)使用半同步,主從都需要加載插件并添加配置文件:
#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.參數(shù)和狀態(tài)
variables:
rpl_semi_sync_master_enabled = ON
表示在master上已經(jīng)開啟半同步復制模式
rpl_semi_sync_master_timeout = 10000
默認為10000毫秒,等于10秒,這個參數(shù)動態(tài)可調(diào),表示主庫在某次事務中,如果等待時間超過10秒,那么則降級為異步復制模式,不再等待SLAVE從庫。如果主庫再次探測到,SLAVE從庫恢復了,則會自動再次回到半同步復制模式。
rpl_semi_sync_master_trace_level = 32
用于開啟半同步復制模式時的調(diào)試級別,默認是32
rpl_semi_sync_master_wait_for_slave_count=1;
該參數(shù)控制主需要等待多少個slave應答,才能返回給客戶端,默認為1。
rpl_semi_sync_master_wait_point = AFTER_SYNC
半同步的方式
status:
Rpl_semi_sync_master_clients
當前半同步復制從的個數(shù),如果是一主多從的架構(gòu),并不包含異步復制從的個數(shù)。
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 | --表示主庫上面的半同步已經(jīng)開啟
| 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 |
+-------------------------------------------+------------+
測試插入一條數(shù)據(jù):
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) --這里插入第一條數(shù)據(jù)用了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個,如果這個值比較大,那么從庫可能有問題,需要優(yōu)化。
| 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;
該參數(shù)控制主需要等待多少個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) --超時之后采用異步復制模式
總結(jié):
1. 在一主多從的架構(gòu)中,如果要開啟半同步復制,并不要求所有的從都是半同步復制。
2. MySQL 5.7極大的提升了半同步復制的性能。
(1)5.6版本的半同步復制,dump thread 承擔了兩份不同且又十分頻繁的任務:傳送binlog 給slave ,還需要等待slave反饋信息,而且這兩個任務是串行的,dump thread 必須等待 slave 返回之后才會傳送下一個 events 事務。dump thread 已然成為整個半同步提高性能的瓶頸。在高并發(fā)業(yè)務場景下,這樣的機制會影響數(shù)據(jù)庫整體的TPS 。
(2)5.7版本的半同步復制中,獨立出一個 ack collector thread ,專門用于接收slave 的反饋信息。這樣master 上有兩個線程獨立工作,可以同時發(fā)送binlog 到slave ,和接收slave的反饋。
參考鏈接:
https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html