一鸭栖、復(fù)制架構(gòu)衍生史
在談這個(gè)特性之前歌馍,我們先來(lái)看看MySQL的復(fù)制架構(gòu)衍生史。
在2000年纤泵,MySQL 3.23.15版本引入了Replication骆姐。Replication作為一種準(zhǔn)實(shí)時(shí)同步方式,得到廣泛應(yīng)用捏题。這個(gè)時(shí)候的Replicaton的實(shí)現(xiàn)涉及到兩個(gè)線程玻褪,一個(gè)在Master,一個(gè)在Slave公荧。Slave的I/O和SQL功能是作為一個(gè)線程带射,從Master獲取到event后直接apply,沒(méi)有relay log循狰。這種方式使得讀取event的速度會(huì)被Slave replay速度拖慢窟社,當(dāng)主備存在較大延遲時(shí)候,會(huì)導(dǎo)致大量binary log沒(méi)有備份到Slave端绪钥。
在2002年灿里,MySQL 4.0.2版本將Slave端event讀取和執(zhí)行獨(dú)立成兩個(gè)線程(IO線程和SQL線程),同時(shí)引入了relay log程腹。IO線程讀取event后寫(xiě)入relay log匣吊,SQL線程從relay log中讀取event然后執(zhí)行。這樣即使SQL線程執(zhí)行慢寸潦,Master的binary log也會(huì)盡可能的同步到Slave色鸳。當(dāng)Master宕機(jī),切換到Slave见转,不會(huì)出現(xiàn)大量數(shù)據(jù)丟失命雀。
在2010年MySQL 5.5版本之前,一直采用的是這種異步復(fù)制的方式斩箫。主庫(kù)的事務(wù)執(zhí)行不會(huì)管備庫(kù)的同步進(jìn)度吏砂,如果備庫(kù)落后撵儿,主庫(kù)不幸crash,那么就會(huì)導(dǎo)致數(shù)據(jù)丟失狐血。于是在MySQL在5.5中就順其自然地引入了半同步復(fù)制统倒,主庫(kù)在應(yīng)答客戶端提交的事務(wù)前需要保證至少一個(gè)從庫(kù)接收并寫(xiě)到relay log中。那么半同步復(fù)制是否可以做到不丟失數(shù)據(jù)呢氛雪?下面分析房匆。
在2016年,MySQL在5.7.17中引入了一個(gè)全新的技術(shù)报亩,稱(chēng)之為InnoDB Group Replication浴鸿。目前官方MySQL 5.7.17基于Group replication的全同步技術(shù)已經(jīng)問(wèn)世,全同步技術(shù)帶來(lái)了更多的數(shù)據(jù)一致性保障弦追。相信是未來(lái)同步技術(shù)一個(gè)重要方向岳链,值得期待。MySQL 5.7 Group Replication
根據(jù)上面提到的這幾種復(fù)制協(xié)議劲件,分別對(duì)應(yīng)MySQL幾種復(fù)制類(lèi)型掸哑,分別是異步、半同步零远、全同步苗分。
對(duì)于異步復(fù)制,主庫(kù)將事務(wù)Binlog事件寫(xiě)入到Binlog文件中牵辣,此時(shí)主庫(kù)只會(huì)通知一下Dump線程發(fā)送這些新的Binlog摔癣,然后主庫(kù)就會(huì)繼續(xù)處理提交操作,而此時(shí)不會(huì)保證這些Binlog傳到任何一個(gè)從庫(kù)節(jié)點(diǎn)上纬向。
對(duì)于全同步復(fù)制择浊,當(dāng)主庫(kù)提交事務(wù)之后,所有的從庫(kù)節(jié)點(diǎn)必須收到逾条,APPLY并且提交這些事務(wù)琢岩,然后主庫(kù)線程才能繼續(xù)做后續(xù)操作。這里面有一個(gè)很明顯的缺點(diǎn)就是师脂,主庫(kù)完成一個(gè)事務(wù)的時(shí)間被拉長(zhǎng)担孔,性能降低。
對(duì)于半同步復(fù)制危彩,是介于全同步復(fù)制和異步復(fù)制之間的一種攒磨,主庫(kù)只需要等待至少一個(gè)從庫(kù)節(jié)點(diǎn)收到并且Flush Binlog到Relay Log文件即可泳桦,主庫(kù)不需要等待所有從庫(kù)給主庫(kù)反饋汤徽。同時(shí),這里只是一個(gè)收到的反饋灸撰,而不是已經(jīng)完全執(zhí)行并且提交的反饋谒府,這樣就節(jié)省了很多時(shí)間拼坎。
二、半同步復(fù)制技術(shù)
我們今天談?wù)摰诙N架構(gòu)完疫。我們知道泰鸡,普通的replication,即MySQL的異步復(fù)制壳鹤,依靠MySQL二進(jìn)制日志也即binary log進(jìn)行數(shù)據(jù)復(fù)制盛龄。比如兩臺(tái)機(jī)器,一臺(tái)主機(jī)(master)芳誓,另外一臺(tái)是從機(jī)(slave)余舶。
1)正常的復(fù)制為:事務(wù)一(t1)寫(xiě)入binlog buffer;dumper線程通知slave有新的事務(wù)t1锹淌;binlog buffer進(jìn)行checkpoint匿值;slave的io線程接收到t1并寫(xiě)入到自己的的relay log;slave的sql線程寫(xiě)入到本地?cái)?shù)據(jù)庫(kù)赂摆。 這時(shí)挟憔,master和slave都能看到這條新的事務(wù),即使master掛了烟号,slave可以提升為新的master绊谭。
2)異常的復(fù)制為:事務(wù)一(t1)寫(xiě)入binlog buffer;dumper線程通知slave有新的事務(wù)t1汪拥;binlog buffer進(jìn)行checkpoint龙誊;slave因?yàn)榫W(wǎng)絡(luò)不穩(wěn)定,一直沒(méi)有收到t1喷楣;master掛掉趟大,slave提升為新的master,t1丟失铣焊。
3)很大的問(wèn)題是:主機(jī)和從機(jī)事務(wù)更新的不同步逊朽,就算是沒(méi)有網(wǎng)絡(luò)或者其他系統(tǒng)的異常,當(dāng)業(yè)務(wù)并發(fā)上來(lái)時(shí)曲伊,slave因?yàn)橐樞驁?zhí)行master批量事務(wù)叽讳,導(dǎo)致很大的延遲。
為了彌補(bǔ)以上幾種場(chǎng)景的不足坟募,MySQL從5.5開(kāi)始推出了半同步復(fù)制岛蚤。相比異步復(fù)制,半同步復(fù)制提高了數(shù)據(jù)完整性懈糯,因?yàn)楹苊鞔_知道涤妒,在一個(gè)事務(wù)提交成功之后,這個(gè)事務(wù)就至少會(huì)存在于兩個(gè)地方赚哗。即在master的dumper線程通知slave后她紫,增加了一個(gè)ack(消息確認(rèn))硅堆,即是否成功收到t1的標(biāo)志碼,也就是dumper線程除了發(fā)送t1到slave贿讹,還承擔(dān)了接收slave的ack工作渐逃。如果出現(xiàn)異常,沒(méi)有收到ack民褂,那么將自動(dòng)降級(jí)為普通的復(fù)制茄菊,直到異常修復(fù)后又會(huì)自動(dòng)變?yōu)榘胪綇?fù)制。
半同步復(fù)制具體特性:
從庫(kù)會(huì)在連接到主庫(kù)時(shí)告訴主庫(kù)赊堪,它是不是配置了半同步买羞。
如果半同步復(fù)制在主庫(kù)端是開(kāi)啟了的,并且至少有一個(gè)半同步復(fù)制的從庫(kù)節(jié)點(diǎn)雹食,那么此時(shí)主庫(kù)的事務(wù)線程在提交時(shí)會(huì)被阻塞并等待畜普,結(jié)果有兩種可能,要么至少一個(gè)從庫(kù)節(jié)點(diǎn)通知它已經(jīng)收到了所有這個(gè)事務(wù)的Binlog事件群叶,要么一直等待直到超過(guò)配置的某一個(gè)時(shí)間點(diǎn)為止吃挑,而此時(shí),半同步復(fù)制將自動(dòng)關(guān)閉街立,轉(zhuǎn)換為異步復(fù)制舶衬。
從庫(kù)節(jié)點(diǎn)只有在接收到某一個(gè)事務(wù)的所有Binlog,將其寫(xiě)入并Flush到Relay Log文件之后赎离,才會(huì)通知對(duì)應(yīng)主庫(kù)上面的等待線程纬霞。
如果在等待過(guò)程中描扯,等待時(shí)間已經(jīng)超過(guò)了配置的超時(shí)時(shí)間,沒(méi)有任何一個(gè)從節(jié)點(diǎn)通知當(dāng)前事務(wù),那么此時(shí)主庫(kù)會(huì)自動(dòng)轉(zhuǎn)換為異步復(fù)制横蜒,當(dāng)至少一個(gè)半同步從節(jié)點(diǎn)趕上來(lái)時(shí)租副,主庫(kù)便會(huì)自動(dòng)轉(zhuǎn)換為半同步方式的復(fù)制舟茶。
半同步復(fù)制必須是在主庫(kù)和從庫(kù)兩端都開(kāi)啟時(shí)才行闸餐,如果在主庫(kù)上沒(méi)打開(kāi),或者在主庫(kù)上開(kāi)啟了而在從庫(kù)上沒(méi)有開(kāi)啟个盆,主庫(kù)都會(huì)使用異步方式復(fù)制脖岛。
半同步復(fù)制潛在問(wèn)題:
先看一下半同步復(fù)制原理圖,如下:
master將每個(gè)事務(wù)寫(xiě)入binlog(sync_binlog=1)颊亮,傳遞到slave刷新到磁盤(pán)(sync_relay=1)柴梆,同時(shí)主庫(kù)提交事務(wù)(commit)。master等待slave反饋收到relay log终惑,只有收到ACK后master才將commit OK結(jié)果反饋給客戶端绍在。
在MySQL 5.5~5.6使用after_commit的模式下,客戶端事務(wù)在存儲(chǔ)引擎層提交后,在得到從庫(kù)確認(rèn)的過(guò)程中揣苏,主庫(kù)宕機(jī)了。此時(shí)件舵,即主庫(kù)在等待Slave ACK的時(shí)候卸察,雖然沒(méi)有返回當(dāng)前客戶端,但事務(wù)已經(jīng)提交铅祸,其他客戶端會(huì)讀取到已提交事務(wù)坑质。如果Slave端還沒(méi)有讀到該事務(wù)的events,同時(shí)主庫(kù)發(fā)生了crash临梗,然后切換到備庫(kù)涡扼。那么之前讀到的事務(wù)就不見(jiàn)了,出現(xiàn)了幻讀盟庞。如下圖所示吃沪,圖片引自Loss-less Semi-Synchronous Replication on MySQL 5.7.2。
如果主庫(kù)永遠(yuǎn)啟動(dòng)不了什猖,那么實(shí)際上在主庫(kù)已經(jīng)成功提交的事務(wù)票彪,在從庫(kù)上是找不到的,也就是數(shù)據(jù)丟失了不狮,這是MySQL不愿意看到的降铸。所以在MySQL 5.7版本中增加了after_sync(無(wú)損復(fù)制)參數(shù),并將其設(shè)置為默認(rèn)半同步方式摇零,解決了數(shù)據(jù)丟失的問(wèn)題推掸。
三、MySQL 5.6半同步復(fù)制配置
具體完整配置可參考:MySQL基于日志點(diǎn)做主從復(fù)制(二)
Master配置
1)安裝半同步模塊并啟動(dòng)(此模塊就在/usr/local/mysql/lib/plugin/semisync_master.so)
1mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> set global rpl_semi_sync_master_enabled = 1;
mysql> set global rpl_semi_sync_master_timeout = 2000;
安裝后啟動(dòng)和定制主從連接錯(cuò)誤的超時(shí)時(shí)間默認(rèn)是10s可改為2s驻仅,一旦有一次超時(shí)自動(dòng)降級(jí)為異步谅畅。(以上內(nèi)容要想永久有效需要寫(xiě)到配置文件中)
[root@localhost ~]# cat /etc/my.cnf
[mysqld]
rpl_semi_sync_master_enabled = 1;
rpl_semi_sync_master_timeout = 2000;
Slave配置
1)安裝半同步模塊并啟動(dòng)
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_slave_enabled = 1;
mysql> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name?????????????????? | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled???? | ON????|
| rpl_semi_sync_slave_trace_level | 32????|
+---------------------------------+-------+
2 rows in set (0.00 sec)
2)從節(jié)點(diǎn)需要重新連接主服務(wù)器半同步才會(huì)生效
mysql> stop slave io_thread;
mysql> start slave io_thread;
PS:如果想卸載異步模塊就使用uninstall即可。
Master上查看是否啟用了半同步
現(xiàn)在半同步已經(jīng)正常工作了噪服,主要看Rpl_semi_sync_master_clients是否不為0铃彰,Rpl_semi_sync_master_status是否為ON。如果Rpl_semi_sync_master_status為OFF芯咧,說(shuō)明出現(xiàn)了網(wǎng)絡(luò)延遲或Slave IO線程延遲牙捉。
那么可以驗(yàn)證一下半同步超時(shí),是否會(huì)自動(dòng)降為異步工作敬飒⌒安可以在Slave上停掉半同步協(xié)議,然后在Master上創(chuàng)建數(shù)據(jù)庫(kù)看一下能不能復(fù)制到Slave上无拗。
Slave
# 關(guān)閉半同步;
mysql> set global rpl_semi_sync_slave_enabled = 0 ;
mysql> stop slave io_thread;
mysql> start slave io_thread;
Master
mysql> create database dbtest;
Query OK, 1 row affected (2.01 sec)
mysql> create database dbtest01;
Query OK, 1 row affected (0.01 sec)
創(chuàng)建第一個(gè)數(shù)據(jù)庫(kù)花了2.01秒带到,而我們前面設(shè)置的超時(shí)時(shí)間是2秒,而創(chuàng)建第二個(gè)數(shù)據(jù)庫(kù)花了0.01秒英染,由此得出結(jié)論是超時(shí)轉(zhuǎn)換為異步傳送揽惹”欢觯可以在Master上查看半同步相關(guān)的參數(shù)值Rpl_semi_sync_master_clients和Rpl_semi_sync_master_status是否正常。
可以看到都自動(dòng)關(guān)閉了搪搏,需要注意一點(diǎn)的是狭握,當(dāng)Slave開(kāi)啟半同步后,或者當(dāng)主從之間網(wǎng)絡(luò)延遲恢復(fù)正常的時(shí)候疯溺,半同步復(fù)制會(huì)自動(dòng)從異步復(fù)制又轉(zhuǎn)為半同步復(fù)制论颅,還是相當(dāng)智能的。
另外個(gè)人在實(shí)際使用中還碰到一種情況從庫(kù)IO線程有延遲時(shí)囱嫩,主庫(kù)會(huì)自動(dòng)把半同步復(fù)制降為異步復(fù)制恃疯;當(dāng)從庫(kù)IO延遲沒(méi)有時(shí),主庫(kù)又會(huì)把異步復(fù)制升級(jí)為半同步復(fù)制墨闲〗裢可以進(jìn)行壓測(cè)模擬,但是此時(shí)查看Master的狀態(tài)跟上面直接關(guān)閉Slave半同步有些不同鸳碧,會(huì)發(fā)現(xiàn)Rpl_semi_sync_master_clients仍然等于1蛙奖,而Rpl_semi_sync_master_status等于OFF。
隨著MySQL 5.7版本的發(fā)布杆兵,半同步復(fù)制技術(shù)升級(jí)為全新的Loss-less Semi-Synchronous Replication架構(gòu)雁仲,其成熟度、數(shù)據(jù)一致性與執(zhí)行效率得到顯著的提升琐脏。
四攒砖、MySQL 5.7半同步復(fù)制的改進(jìn)
現(xiàn)在我們已經(jīng)知道,在半同步環(huán)境下日裙,主庫(kù)是在事務(wù)提交之后等待Slave ACK吹艇,所以才會(huì)有數(shù)據(jù)不一致問(wèn)題。所以這個(gè)Slave ACK在什么時(shí)間去等待昂拂,也是一個(gè)很關(guān)鍵的問(wèn)題了受神。因此MySQL針對(duì)半同步復(fù)制的問(wèn)題,在5.7.2引入了Loss-less Semi-Synchronous格侯,在調(diào)用binlog sync之后鼻听,engine層commit之前等待Slave ACK。這樣只有在確認(rèn)Slave收到事務(wù)events后联四,事務(wù)才會(huì)提交撑碴。在commit之前等待Slave ACK,同時(shí)可以堆積事務(wù)朝墩,利于group commit醉拓,有利于提升性能。
MySQL 5.7安裝半同步模塊,命令如下:
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.00 sec)
看一下相關(guān)狀態(tài)信息
mysql> show global variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name???????????????????????????? | Value??????|
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled??????????????| OFF????????|
| rpl_semi_sync_master_timeout??????????????| 10000??????|
| 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 |
+-------------------------------------------+------------+
6 rows in set (0.00 sec)
支持無(wú)損復(fù)制(Loss-less Semi-Synchronous)
在Loss-less Semi-Synchronous模式下亿卤,master在調(diào)用binlog sync之后愤兵,engine層commit之前等待Slave ACK(需要收到至少一個(gè)Slave節(jié)點(diǎn)回復(fù)的ACK后)。這樣只有在確認(rèn)Slave收到事務(wù)events后排吴,master事務(wù)才會(huì)提交秆乳,然后把結(jié)果返回給客戶端。此時(shí)此事務(wù)才對(duì)其他事務(wù)可見(jiàn)傍念。在這種模式下解決了after_commit模式帶來(lái)的幻讀和數(shù)據(jù)丟失問(wèn)題矫夷,因?yàn)橹鲙?kù)沒(méi)有提交事務(wù)葛闷。但也會(huì)有個(gè)問(wèn)題憋槐,假設(shè)主庫(kù)在存儲(chǔ)引擎提交之前掛了,那么很明顯這個(gè)事務(wù)是不成功的淑趾,但由于對(duì)應(yīng)的Binlog已經(jīng)做了Sync操作阳仔,從庫(kù)已經(jīng)收到了這些Binlog,并且執(zhí)行成功扣泊,相當(dāng)于在從庫(kù)上多了數(shù)據(jù)近范,也算是有問(wèn)題的,但多了數(shù)據(jù)延蟹,問(wèn)題一般不算嚴(yán)重评矩。這個(gè)問(wèn)題可以這樣理解,作為MySQL阱飘,在沒(méi)辦法解決分布式數(shù)據(jù)一致性問(wèn)題的情況下斥杜,它能保證的是不丟數(shù)據(jù),多了數(shù)據(jù)總比丟數(shù)據(jù)要好沥匈。
無(wú)損復(fù)制其實(shí)就是對(duì)semi sync增加了rpl_semi_sync_master_wait_point參數(shù)蔗喂,來(lái)控制半同步模式下主庫(kù)在返回給會(huì)話事務(wù)成功之前提交事務(wù)的方式。rpl_semi_sync_master_wait_point該參數(shù)有兩個(gè)值:AFTER_COMMIT和AFTER_SYNC
第一個(gè)值:AFTER_COMMIT(5.6默認(rèn)值)
master將每個(gè)事務(wù)寫(xiě)入binlog(sync_binlog=1)高帖,傳遞到slave刷新到磁盤(pán)(sync_relay=1)缰儿,同時(shí)主庫(kù)提交事務(wù)。master等待slave反饋收到relay log散址,只有收到ACK后master才將commit OK結(jié)果反饋給客戶端乖阵。
第二個(gè)值:AFTER_SYNC(5.7默認(rèn)值,但5.6中無(wú)此模式)
master將每個(gè)事務(wù)寫(xiě)入binlog , 傳遞到slave刷新到磁盤(pán)(relay log)预麸。master等待slave反饋接收到relay log的ack之后义起,再提交事務(wù)并且返回commit OK結(jié)果給客戶端。 即使主庫(kù)crash师崎,所有在主庫(kù)上已經(jīng)提交的事務(wù)都能保證已經(jīng)同步到slave的relay log中默终。
半同步復(fù)制與無(wú)損復(fù)制的對(duì)比
1.1 ACK的時(shí)間點(diǎn)不同
半同步復(fù)制在InnoDB層的Commit Log后等待ACK,主從切換會(huì)有數(shù)據(jù)丟失風(fēng)險(xiǎn)。
無(wú)損復(fù)制在MySQL Server層的Write binlog后等待ACK齐蔽,主從切換會(huì)有數(shù)據(jù)變多風(fēng)險(xiǎn)两疚。
1.2 主從數(shù)據(jù)一致性
半同步復(fù)制意味著在Master節(jié)點(diǎn)上,這個(gè)剛剛提交的事物對(duì)數(shù)據(jù)庫(kù)的修改含滴,對(duì)其他事物是可見(jiàn)的诱渤。因此,如果在等待Slave ACK的時(shí)候crash了谈况,那么會(huì)對(duì)其他事務(wù)出現(xiàn)幻讀勺美,數(shù)據(jù)丟失。
無(wú)損復(fù)制在write binlog完成后碑韵,就傳輸binlog赡茸,但還沒(méi)有去寫(xiě)commit log,意味著當(dāng)前這個(gè)事物對(duì)數(shù)據(jù)庫(kù)的修改祝闻,其他事物也是不可見(jiàn)的占卧。因此,不會(huì)出現(xiàn)幻讀联喘,數(shù)據(jù)丟失風(fēng)險(xiǎn)华蜒。
因此5.7引入了無(wú)損復(fù)制(after_sync)模式,帶來(lái)的主要收益是解決after_commit導(dǎo)致的master crash后數(shù)據(jù)丟失問(wèn)題豁遭,因此在引入after_sync模式后叭喜,所有提交的數(shù)據(jù)已經(jīng)都被復(fù)制,故障切換時(shí)數(shù)據(jù)一致性將得到提升蓖谢。
性能提升捂蕴,支持發(fā)送binlog和接受ack的異步化
舊版本的semi sync受限于dump thread ,原因是dump thread承擔(dān)了兩份不同且又十分頻繁的任務(wù):傳送binlog給slave 蜈抓,還需要等待slave反饋信息启绰,而且這兩個(gè)任務(wù)是串行的,dump thread必須等待slave返回之后才會(huì)傳送下一個(gè)events事務(wù)沟使。dump thread已然成為整個(gè)半同步提高性能的瓶頸委可。在高并發(fā)業(yè)務(wù)場(chǎng)景下,這樣的機(jī)制會(huì)影響數(shù)據(jù)庫(kù)整體的TPS 腊嗡。
為了解決上述問(wèn)題着倾,在5.7版本的semi sync框架中,獨(dú)立出一個(gè)Ack Receiver線程 燕少,專(zhuān)門(mén)用于接收slave返回的ack請(qǐng)求卡者,這將之前dump線程的發(fā)送和接受工作分為了兩個(gè)線程來(lái)處理。這樣master上有兩個(gè)線程獨(dú)立工作客们,可以同時(shí)發(fā)送binlog到slave崇决,和接收slave的ack信息材诽。因此半同步復(fù)制得到了極大的性能提升。這也是MySQL 5.7發(fā)布時(shí)號(hào)稱(chēng)的Faster semi-sync replication恒傻。
但是在MySQL 5.7.17之前脸侥,這個(gè)Ack Receiver線程采用了select機(jī)制來(lái)監(jiān)聽(tīng)slave返回的結(jié)果,然而select機(jī)制監(jiān)控的文件句柄只能是0-1024盈厘,當(dāng)超過(guò)1024時(shí)睁枕,用戶在MySQL的錯(cuò)誤日志中或許會(huì)收到類(lèi)似如下的報(bào)錯(cuò),更有甚者會(huì)導(dǎo)致MySQL發(fā)生宕機(jī)沸手。
semi-sync master failed on net_flush() before waiting for slave reply.
MySQL 5.7.17版本開(kāi)始外遇,官方修復(fù)了這個(gè)bug,開(kāi)始使用poll機(jī)制來(lái)替換原來(lái)的select機(jī)制契吉,從而可以避免上面的問(wèn)題跳仿。其實(shí)poll調(diào)用本質(zhì)上和select沒(méi)有區(qū)別,只是在I/O句柄數(shù)理論上沒(méi)有上限了栅隐,原因是它是基于鏈表來(lái)存儲(chǔ)的塔嬉。但是同樣有缺點(diǎn):比如大量的fd的數(shù)組被整體復(fù)制于用戶態(tài)和內(nèi)核地址空間之間玩徊,而不管這樣的復(fù)制是不是有意義租悄。poll還有一個(gè)特點(diǎn)是“水平觸發(fā)”,如果報(bào)告了fd后恩袱,沒(méi)有被處理泣棋,那么下次poll時(shí)會(huì)再次報(bào)告該fd。
其實(shí)在高性能軟件中都是用另外一種調(diào)用機(jī)制畔塔,名為epoll潭辈,高性能的代表,比如Nginx澈吨,haproxy等都是使用epoll把敢。可能poll的復(fù)雜性比epoll低谅辣,另外對(duì)于ack receiver線程來(lái)說(shuō)可能poll足矣修赞。
性能提升,控制主庫(kù)接收slave寫(xiě)事務(wù)成功反饋數(shù)量
MySQL 5.7新增了rpl_semi_sync_master_wait_slave_count參數(shù)桑阶,可以用來(lái)控制主庫(kù)接受多少個(gè)slave寫(xiě)事務(wù)成功反饋柏副,給高可用架構(gòu)切換提供了靈活性。如圖所示蚣录,當(dāng)count值為2時(shí)割择,master需等待兩個(gè)slave的ack。
性能提升, Binlog互斥鎖改進(jìn)
舊版本半同步復(fù)制在主提交binlog的寫(xiě)會(huì)話和dump thread讀binlog的操作都會(huì)對(duì)binlog添加互斥鎖萎河,導(dǎo)致binlog文件的讀寫(xiě)是串行化的荔泳,存在并發(fā)度的問(wèn)題蕉饼。
MySQL 5.7對(duì)binlog lock進(jìn)行了以下兩方面優(yōu)化:
1. 移除了dump thread對(duì)binlog的互斥鎖。
2. 加入了安全邊際保證binlog的讀安全玛歌。
可以看到從replication功能引入后椎椰,官方MySQL一直在不停的完善,前進(jìn)沾鳄。同時(shí)我們可以發(fā)現(xiàn)當(dāng)前原生的MySQL主備復(fù)制實(shí)現(xiàn)實(shí)際上很難在滿足數(shù)據(jù)一致性的前提下做到高可用慨飘、高性能。
轉(zhuǎn)自:http://www.ywnds.com/?p=7023