京東一面:MySQL 主備延遲有哪些坑?主備切換策略
大家好,我是Tom哥
作為一名開(kāi)發(fā)同學(xué),大家對(duì) MySQL 一定不陌生,像常見(jiàn)的 事務(wù)特性、隔離級(jí)別 、索引等也都是老生常談。
今天,我們就來(lái)聊個(gè)深度話題,關(guān)于 MySQL 的 高可用
一、什么是高可用?
維基百科定義:
高可用性(high availability,縮寫(xiě) HA),指系統(tǒng)無(wú)中斷地執(zhí)行其功能的能力,代表系統(tǒng)的可用性程度。高可用性通常通過(guò)提高系統(tǒng)的容錯(cuò)能力來(lái)實(shí)現(xiàn)。
MySQL 的高可用是如何實(shí)現(xiàn)的呢?
首先,我們來(lái)看張圖

過(guò)程:
- 開(kāi)始時(shí),處理流程主要是
場(chǎng)景一 - 客戶端
讀、寫(xiě),訪問(wèn)的是主庫(kù) - 主庫(kù)通過(guò)某種機(jī)制,將數(shù)據(jù)實(shí)時(shí)同步給備庫(kù)
- 當(dāng)主庫(kù)突然發(fā)生故障(如:磁盤(pán)損壞等),無(wú)法正常響應(yīng)客戶端的請(qǐng)求。此時(shí)會(huì)
自動(dòng)主備切換,進(jìn)入場(chǎng)景二 - 客戶端讀寫(xiě),訪問(wèn)的是備庫(kù)(此時(shí)備庫(kù)升級(jí)為新主庫(kù))

看似天衣無(wú)縫,那是不是可以高枕無(wú)憂了呢???兄弟,想多了
主備切換,確實(shí)能滿足高可用。但有個(gè)前提,主備庫(kù)的數(shù)據(jù)要同步。
不過(guò),數(shù)據(jù)同步是個(gè)異步操作,不可能做到實(shí)時(shí),所以說(shuō)主備延遲是一定存在的
二、什么是主備延遲?

- 主庫(kù)完成一個(gè)事務(wù),寫(xiě)入binlog。binlog 中有一個(gè)時(shí)間字段,用于記錄主庫(kù)寫(xiě)入的時(shí)間【時(shí)刻 t1】
- binlog 同步給備庫(kù),備庫(kù)接收并存儲(chǔ)到中繼日志 【時(shí)刻 t2】
- 備庫(kù)SQL執(zhí)行線程執(zhí)行binlog,數(shù)據(jù)寫(xiě)入到備庫(kù)表中 【時(shí)刻 t3】
主備延遲時(shí)間計(jì)算公式:
t3 - t1
有沒(méi)有簡(jiǎn)單命令,直接查看。在備庫(kù)執(zhí)行 show slave status 命令
seconds_behind_master,表示當(dāng)前備庫(kù)延遲了多少秒
心細(xì)的同學(xué)會(huì)有疑問(wèn)了, t3 和 t1 分屬于兩臺(tái)機(jī)器,如果時(shí)鐘不一致怎么辦?
初始化時(shí),備庫(kù)連接到主庫(kù),會(huì)執(zhí)行 SELECT UNIX_TIMESTAMP() 來(lái)獲得當(dāng)前主庫(kù)的系統(tǒng)時(shí)間。
如果發(fā)現(xiàn)主庫(kù)的系統(tǒng)時(shí)間與備庫(kù)不一致,備庫(kù)在計(jì)算 seconds_behind_master 會(huì)自動(dòng)減掉這個(gè)差值。
注意:
binlog 數(shù)據(jù)傳輸?shù)臅r(shí)間(t2 - t1)非常短,可以忽略。主要延遲花費(fèi)在備庫(kù)執(zhí)行binlog日志
三、主備延遲常見(jiàn)原因
1、備庫(kù)機(jī)器配置差
這個(gè)不難理解,“門(mén)當(dāng)戶對(duì)”、“志同道合”,如果主備機(jī)器的性能差別大,直接導(dǎo)致備庫(kù)的同步速度跟不上主庫(kù)的生產(chǎn)節(jié)奏。
就像跑步一樣,落后差距會(huì)越來(lái)越大。
解決方案:
1、升級(jí)備庫(kù)的機(jī)器配置
2、備庫(kù)干私活
備庫(kù)除了服務(wù)于正常的讀業(yè)務(wù)外,是否有被其他特殊業(yè)務(wù)征用,如:運(yùn)營(yíng)數(shù)據(jù)統(tǒng)計(jì)等,這類(lèi)操作非常消耗系統(tǒng)資源,也會(huì)影響數(shù)據(jù)同步速度。
解決方案:
可以借助大數(shù)據(jù)平臺(tái),數(shù)據(jù)異構(gòu),滿足各種這些特殊的統(tǒng)計(jì)類(lèi)查詢。
3、大事務(wù)
我們知道 binglog 是在事務(wù)提交時(shí)才生成的。
如果是處理大事務(wù),執(zhí)行時(shí)間比較長(zhǎng)(比如 5分鐘)。雖然備庫(kù)很快拿到 binlog,但是在備庫(kù)回放執(zhí)行也要花費(fèi)差不多的時(shí)間,也要 5分鐘 (備庫(kù)中,只有這個(gè)事務(wù)執(zhí)行完提交,備庫(kù)才真正對(duì)外可見(jiàn)),從而導(dǎo)致主備延遲很大。
比如 delete 操作,慎用 delete from 表名,建議采用分批刪除,減少大事務(wù)。
四、主庫(kù)不可用,主備切換有哪些策略?
1、可靠?jī)?yōu)先

當(dāng)主庫(kù)A 發(fā)生故障不可用時(shí),開(kāi)始進(jìn)入主備切換
- 首先,判斷 B庫(kù)
seconds_behind_master是否小于設(shè)定的閾值(比如 4 秒),如果滿足條件 - 將 A庫(kù) 改為只讀狀態(tài),將 readonly 設(shè)置為 true。斷掉 A 庫(kù)的寫(xiě)入操作,保證不會(huì)有新的寫(xiě)流量進(jìn)來(lái)
- 判斷 B庫(kù)的 ?
seconds_behind_master,直到為 0 - 修改 B庫(kù) 為
讀、寫(xiě)狀態(tài) - 客戶端的請(qǐng)求打到 B庫(kù)
此時(shí),主備切換完成。
優(yōu)點(diǎn):
數(shù)據(jù)不會(huì)丟失,所以我們稱(chēng)為可靠性高
缺點(diǎn):
中間有個(gè)階段,A庫(kù)和B庫(kù)都是只讀狀態(tài),此時(shí)系統(tǒng)對(duì)外不能提供寫(xiě)服務(wù)。
2、可用優(yōu)先
當(dāng)然我們也可以不用等主備數(shù)據(jù)同步完成,在一開(kāi)始時(shí)就直接將流量切到備庫(kù)。
這樣備庫(kù)的流量就可能有兩個(gè)來(lái)源:
- 主庫(kù)之前的剩余流量 binlog
- 客戶端新請(qǐng)求進(jìn)來(lái)的流量
兩部分流量沖擊,會(huì)對(duì) 數(shù)據(jù)一致性 造成一些影響。
我們來(lái)做個(gè)實(shí)驗(yàn):
首次創(chuàng)建一個(gè)用戶表:
CREATE?TABLE?`person`?(
??`id`??bigint(20)?unsigned??NOT?NULL?AUTO_INCREMENT,
??`name`?varchar(32)?,
??PRIMARY?KEY?(`id`)
)?ENGINE=InnoDB;
插入2條記錄
insert?into?person(name)?values?("tom");
insert?into?person(name)?values?("jerry");
實(shí)驗(yàn)一:
將 binlog 的格式設(shè)為 binlog_format=row
說(shuō)明:row 模式,寫(xiě) binlog 時(shí)會(huì)記錄所有字段的值

庫(kù)A 、庫(kù)B 在做數(shù)據(jù)同步時(shí),都會(huì)報(bào)主鍵沖突,最后只有一行數(shù)據(jù)不一致,但是會(huì)丟數(shù)據(jù)。
優(yōu)點(diǎn):同步過(guò)程中,出現(xiàn)問(wèn)題能夠及時(shí)發(fā)現(xiàn)。
實(shí)驗(yàn)二:
將 binlog 格式設(shè)置為 ?statement 或者 mixed

按照 SQL 原始語(yǔ)句同步 binlog,可以看到,數(shù)據(jù)條數(shù)不會(huì)少,但是主鍵id會(huì)出現(xiàn)混亂。
3、結(jié)論
本著 "攘外必先安內(nèi)" ,保證內(nèi)部的數(shù)據(jù)的正確性是我們的首選。所以,一般建議大家選擇 可靠?jī)?yōu)先。
但是可靠?jī)?yōu)先可能會(huì)導(dǎo)致一定時(shí)間內(nèi),數(shù)據(jù)庫(kù)不可用。這個(gè)時(shí)間值取決于主備延遲的時(shí)間大小。
所以,我們應(yīng)盡可能縮短主備庫(kù)的延遲時(shí)間大小,這樣一旦主庫(kù)發(fā)生故障,備庫(kù)才會(huì)更快的同步完數(shù)據(jù),主備切換才能完成,服務(wù)才能更快恢復(fù)。
推薦閱讀:
【萬(wàn)字長(zhǎng)文】創(chuàng)業(yè)公司就應(yīng)該技術(shù)選型 Spring Cloud Alibaba
Redis 使用 List 實(shí)現(xiàn)消息隊(duì)列的利與弊
阿里一面:講一講各個(gè)Spring框架之間的關(guān)系
歡迎關(guān)注微信公眾號(hào):互聯(lián)網(wǎng)全棧架構(gòu),收取更多有價(jià)值的信息。
