免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
25.MySQL是怎么保證高可用的

在上一篇文章中,我和你介紹了binlog的基本內(nèi)容,在一個(gè)主備關(guān)系中,每個(gè)備庫接收主庫的binlog并執(zhí)行。

正常情況下,只要主庫執(zhí)行更新生成的所有binlog,都可以傳到備庫并被正確地執(zhí)行,備庫就能達(dá)到跟主庫一致的狀態(tài),這就是最終一致性。

但是,MySQL要提供高可用能力,只有最終一致性是不夠的。為什么這么說呢?今天我就著重和你分析一下。

這里,我再放一次上一篇文章中講到的雙M結(jié)構(gòu)的主備切換流程圖。

圖 1 MySQL主備切換流程--雙M結(jié)構(gòu)

主備延遲

主備切換可能是一個(gè)主動(dòng)運(yùn)維動(dòng)作,比如軟件升級(jí)、主庫所在機(jī)器按計(jì)劃下線等,也可能是被動(dòng)操作,比如主庫所在機(jī)器掉電。

接下來,我們先一起看看主動(dòng)切換的場(chǎng)景。

在介紹主動(dòng)切換流程的詳細(xì)步驟之前,我要先跟你說明一個(gè)概念,即“同步延遲”。與數(shù)據(jù)同步有關(guān)的時(shí)間點(diǎn)主要包括以下三個(gè):

  1. 主庫A執(zhí)行完成一個(gè)事務(wù),寫入binlog,我們把這個(gè)時(shí)刻記為T1;

  2. 之后傳給備庫B,我們把備庫B接收完這個(gè)binlog的時(shí)刻記為T2;

  3. 備庫B執(zhí)行完成這個(gè)事務(wù),我們把這個(gè)時(shí)刻記為T3。

所謂主備延遲,就是同一個(gè)事務(wù),在備庫執(zhí)行完成的時(shí)間和主庫執(zhí)行完成的時(shí)間之間的差值,也就是T3-T1。

你可以在備庫上執(zhí)行show slave status命令,它的返回結(jié)果里面會(huì)顯示seconds_behind_master,用于表示當(dāng)前備庫延遲了多少秒。

seconds_behind_master的計(jì)算方法是這樣的:

  1. 每個(gè)事務(wù)的binlog 里面都有一個(gè)時(shí)間字段,用于記錄主庫上寫入的時(shí)間;

  2. 備庫取出當(dāng)前正在執(zhí)行的事務(wù)的時(shí)間字段的值,計(jì)算它與當(dāng)前系統(tǒng)時(shí)間的差值,得到seconds_behind_master。

可以看到,其實(shí)seconds_behind_master這個(gè)參數(shù)計(jì)算的就是T3-T1。所以,我們可以用seconds_behind_master來作為主備延遲的值,這個(gè)值的時(shí)間精度是秒。

你可能會(huì)問,如果主備庫機(jī)器的系統(tǒng)時(shí)間設(shè)置不一致,會(huì)不會(huì)導(dǎo)致主備延遲的值不準(zhǔn)?

其實(shí)不會(huì)的。因?yàn)?,備庫連接到主庫的時(shí)候,會(huì)通過執(zhí)行SELECT UNIX_TIMESTAMP()函數(shù)來獲得當(dāng)前主庫的系統(tǒng)時(shí)間。如果這時(shí)候發(fā)現(xiàn)主庫的系統(tǒng)時(shí)間與自己不一致,備庫在執(zhí)行seconds_behind_master計(jì)算的時(shí)候會(huì)自動(dòng)扣掉這個(gè)差值。

需要說明的是,在網(wǎng)絡(luò)正常的時(shí)候,日志從主庫傳給備庫所需的時(shí)間是很短的,即T2-T1的值是非常小的。也就是說,網(wǎng)絡(luò)正常情況下,主備延遲的主要來源是備庫接收完binlog和執(zhí)行完這個(gè)事務(wù)之間的時(shí)間差。

所以說,主備延遲最直接的表現(xiàn)是,備庫消費(fèi)中轉(zhuǎn)日志(relay log)的速度,比主庫生產(chǎn)binlog的速度要慢。接下來,我就和你一起分析下,這可能是由哪些原因?qū)е碌摹?/p>

主備延遲的來源

首先,有些部署條件下,備庫所在機(jī)器的性能要比主庫所在的機(jī)器性能差。

一般情況下,有人這么部署時(shí)的想法是,反正備庫沒有請(qǐng)求,所以可以用差一點(diǎn)兒的機(jī)器?;蛘?,他們會(huì)把20個(gè)主庫放在4臺(tái)機(jī)器上,而把備庫集中在一臺(tái)機(jī)器上。

其實(shí)我們都知道,更新請(qǐng)求對(duì)IOPS的壓力,在主庫和備庫上是無差別的。所以,做這種部署時(shí),一般都會(huì)將備庫設(shè)置為“非雙1”的模式。

但實(shí)際上,更新過程中也會(huì)觸發(fā)大量的讀操作。所以,當(dāng)備庫主機(jī)上的多個(gè)備庫都在爭(zhēng)搶資源的時(shí)候,就可能會(huì)導(dǎo)致主備延遲了。

當(dāng)然,這種部署現(xiàn)在比較少了。因?yàn)橹鱾淇赡馨l(fā)生切換,備庫隨時(shí)可能變成主庫,所以主備庫選用相同規(guī)格的機(jī)器,并且做對(duì)稱部署,是現(xiàn)在比較常見的情況。

追問1:但是,做了對(duì)稱部署以后,還可能會(huì)有延遲。這是為什么呢?

這就是第二種常見的可能了,即備庫的壓力大。一般的想法是,主庫既然提供了寫能力,那么備庫可以提供一些讀能力?;蛘咭恍┻\(yùn)營(yíng)后臺(tái)需要的分析語句,不能影響正常業(yè)務(wù),所以只能在備庫上跑。

我真就見過不少這樣的情況。由于主庫直接影響業(yè)務(wù),大家使用起來會(huì)比較克制,反而忽視了備庫的壓力控制。結(jié)果就是,備庫上的查詢耗費(fèi)了大量的CPU資源,影響了同步速度,造成主備延遲。

這種情況,我們一般可以這么處理:

  1. 一主多從。除了備庫外,可以多接幾個(gè)從庫,讓這些從庫來分擔(dān)讀的壓力。

  2. 通過binlog輸出到外部系統(tǒng),比如Hadoop這類系統(tǒng),讓外部系統(tǒng)提供統(tǒng)計(jì)類查詢的能力。

其中,一主多從的方式大都會(huì)被采用。因?yàn)樽鳛閿?shù)據(jù)庫系統(tǒng),還必須保證有定期全量備份的能力。而從庫,就很適合用來做備份。

備注:這里需要說明一下,從庫和備庫在概念上其實(shí)差不多。在我們這個(gè)專欄里,為了方便描述,我把會(huì)在HA過程中被選成新主庫的,稱為備庫,其他的稱為從庫。

追問2:采用了一主多從,保證備庫的壓力不會(huì)超過主庫,還有什么情況可能導(dǎo)致主備延遲嗎?

這就是第三種可能了,即大事務(wù)。

大事務(wù)這種情況很好理解。因?yàn)橹鲙焐媳仨毜仁聞?wù)執(zhí)行完成才會(huì)寫入binlog,再傳給備庫。所以,如果一個(gè)主庫上的語句執(zhí)行10分鐘,那這個(gè)事務(wù)很可能就會(huì)導(dǎo)致從庫延遲10分鐘。

不知道你所在公司的DBA有沒有跟你這么說過:不要一次性地用delete語句刪除太多數(shù)據(jù)。其實(shí),這就是一個(gè)典型的大事務(wù)場(chǎng)景。

比如,一些歸檔類的數(shù)據(jù),平時(shí)沒有注意刪除歷史數(shù)據(jù),等到空間快滿了,業(yè)務(wù)開發(fā)人員要一次性地刪掉大量歷史數(shù)據(jù)。同時(shí),又因?yàn)橐苊庠诟叻迤诓僮鲿?huì)影響業(yè)務(wù)(至少有這個(gè)意識(shí)還是很不錯(cuò)的),所以會(huì)在晚上執(zhí)行這些大量數(shù)據(jù)的刪除操作。

結(jié)果,負(fù)責(zé)的DBA同學(xué)半夜就會(huì)收到延遲報(bào)警。然后,DBA團(tuán)隊(duì)就要求你后續(xù)再刪除數(shù)據(jù)的時(shí)候,要控制每個(gè)事務(wù)刪除的數(shù)據(jù)量,分成多次刪除。

另一種典型的大事務(wù)場(chǎng)景,就是大表DDL。這個(gè)場(chǎng)景,我在前面的文章中介紹過。處理方案就是,計(jì)劃內(nèi)的DDL,建議使用gh-ost方案(這里,你可以再回顧下第13篇文章《為什么表數(shù)據(jù)刪掉一半,表文件大小不變?》中的相關(guān)內(nèi)容)。

追問3:如果主庫上也不做大事務(wù)了,還有什么原因會(huì)導(dǎo)致主備延遲嗎?

造成主備延遲還有一個(gè)大方向的原因,就是備庫的并行復(fù)制能力。這個(gè)話題,我會(huì)留在下一篇文章再和你詳細(xì)介紹。

其實(shí)還是有不少其他情況會(huì)導(dǎo)致主備延遲,如果你還碰到過其他場(chǎng)景,歡迎你在評(píng)論區(qū)給我留言,我來和你一起分析、討論。

由于主備延遲的存在,所以在主備切換的時(shí)候,就相應(yīng)的有不同的策略。

可靠性優(yōu)先策略

在圖1的雙M結(jié)構(gòu)下,從狀態(tài)1到狀態(tài)2切換的詳細(xì)過程是這樣的:

  1. 判斷備庫B現(xiàn)在的seconds_behind_master,如果小于某個(gè)值(比如5秒)繼續(xù)下一步,否則持續(xù)重試這一步;

  2. 把主庫A改成只讀狀態(tài),即把readonly設(shè)置為true;

  3. 判斷備庫B的seconds_behind_master的值,直到這個(gè)值變成0為止;

  4. 把備庫B改成可讀寫狀態(tài),也就是把readonly 設(shè)置為false;

  5. 把業(yè)務(wù)請(qǐng)求切到備庫B。

這個(gè)切換流程,一般是由專門的HA系統(tǒng)來完成的,我們暫時(shí)稱之為可靠性優(yōu)先流程。

圖2 MySQL可靠性優(yōu)先主備切換流程

備注:圖中的SBM,是seconds_behind_master參數(shù)的簡(jiǎn)寫。

可以看到,這個(gè)切換流程中是有不可用時(shí)間的。因?yàn)樵诓襟E2之后,主庫A和備庫B都處于readonly狀態(tài),也就是說這時(shí)系統(tǒng)處于不可寫狀態(tài),直到步驟5完成后才能恢復(fù)。

在這個(gè)不可用狀態(tài)中,比較耗費(fèi)時(shí)間的是步驟3,可能需要耗費(fèi)好幾秒的時(shí)間。這也是為什么需要在步驟1先做判斷,確保seconds_behind_master的值足夠小。

試想如果一開始主備延遲就長(zhǎng)達(dá)30分鐘,而不先做判斷直接切換的話,系統(tǒng)的不可用時(shí)間就會(huì)長(zhǎng)達(dá)30分鐘,這種情況一般業(yè)務(wù)都是不可接受的。

當(dāng)然,系統(tǒng)的不可用時(shí)間,是由這個(gè)數(shù)據(jù)可靠性優(yōu)先的策略決定的。你也可以選擇可用性優(yōu)先的策略,來把這個(gè)不可用時(shí)間幾乎降為0。

可用性優(yōu)先策略

如果我強(qiáng)行把步驟4、5調(diào)整到最開始執(zhí)行,也就是說不等主備數(shù)據(jù)同步,直接把連接切到備庫B,并且讓備庫B可以讀寫,那么系統(tǒng)幾乎就沒有不可用時(shí)間了。

我們把這個(gè)切換流程,暫時(shí)稱作可用性優(yōu)先流程。這個(gè)切換流程的代價(jià),就是可能出現(xiàn)數(shù)據(jù)不一致的情況。

接下來,我就和你分享一個(gè)可用性優(yōu)先流程產(chǎn)生數(shù)據(jù)不一致的例子。假設(shè)有一個(gè)表 t:

mysql> CREATE TABLE `t` (  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,  `c` int(11) unsigned DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB;insert into t(c) values(1),(2),(3);

這個(gè)表定義了一個(gè)自增主鍵id,初始化數(shù)據(jù)后,主庫和備庫上都是3行數(shù)據(jù)。接下來,業(yè)務(wù)人員要繼續(xù)在表t上執(zhí)行兩條插入語句的命令,依次是:

insert into t(c) values(4);insert into t(c) values(5);

假設(shè),現(xiàn)在主庫上其他的數(shù)據(jù)表有大量的更新,導(dǎo)致主備延遲達(dá)到5秒。在插入一條c=4的語句后,發(fā)起了主備切換。

圖3是可用性優(yōu)先策略,且binlog_format=mixed時(shí)的切換流程和數(shù)據(jù)結(jié)果。

圖3 可用性優(yōu)先策略,且binlog_format=mixed

現(xiàn)在,我們一起分析下這個(gè)切換流程:

  1. 步驟2中,主庫A執(zhí)行完insert語句,插入了一行數(shù)據(jù)(4,4),之后開始進(jìn)行主備切換。

  2. 步驟3中,由于主備之間有5秒的延遲,所以備庫B還沒來得及應(yīng)用“插入c=4”這個(gè)中轉(zhuǎn)日志,就開始接收客戶端“插入 c=5”的命令。

  3. 步驟4中,備庫B插入了一行數(shù)據(jù)(4,5),并且把這個(gè)binlog發(fā)給主庫A。

  4. 步驟5中,備庫B執(zhí)行“插入c=4”這個(gè)中轉(zhuǎn)日志,插入了一行數(shù)據(jù)(5,4)。而直接在備庫B執(zhí)行的“插入c=5”這個(gè)語句,傳到主庫A,就插入了一行新數(shù)據(jù)(5,5)。

最后的結(jié)果就是,主庫A和備庫B上出現(xiàn)了兩行不一致的數(shù)據(jù)??梢钥吹剑@個(gè)數(shù)據(jù)不一致,是由可用性優(yōu)先流程導(dǎo)致的。

那么,如果我還是用可用性優(yōu)先策略,但設(shè)置binlog_format=row,情況又會(huì)怎樣呢?

因?yàn)閞ow格式在記錄binlog的時(shí)候,會(huì)記錄新插入的行的所有字段值,所以最后只會(huì)有一行不一致。而且,兩邊的主備同步的應(yīng)用線程會(huì)報(bào)錯(cuò)duplicate key error并停止。也就是說,這種情況下,備庫B的(5,4)和主庫A的(5,5)這兩行數(shù)據(jù),都不會(huì)被對(duì)方執(zhí)行。

圖4中我畫出了詳細(xì)過程,你可以自己再分析一下。

圖4 可用性優(yōu)先策略,且binlog_format=row

從上面的分析中,你可以看到一些結(jié)論:

  1. 使用row格式的binlog時(shí),數(shù)據(jù)不一致的問題更容易被發(fā)現(xiàn)。而使用mixed或者statement格式的binlog時(shí),數(shù)據(jù)很可能悄悄地就不一致了。如果你過了很久才發(fā)現(xiàn)數(shù)據(jù)不一致的問題,很可能這時(shí)的數(shù)據(jù)不一致已經(jīng)不可查,或者連帶造成了更多的數(shù)據(jù)邏輯不一致。

  2. 主備切換的可用性優(yōu)先策略會(huì)導(dǎo)致數(shù)據(jù)不一致。因此,大多數(shù)情況下,我都建議你使用可靠性優(yōu)先策略。畢竟對(duì)數(shù)據(jù)服務(wù)來說的話,數(shù)據(jù)的可靠性一般還是要優(yōu)于可用性的。

但事無絕對(duì),有沒有哪種情況數(shù)據(jù)的可用性優(yōu)先級(jí)更高呢?

答案是,有的。

我曾經(jīng)碰到過這樣的一個(gè)場(chǎng)景:

  • 有一個(gè)庫的作用是記錄操作日志。這時(shí)候,如果數(shù)據(jù)不一致可以通過binlog來修補(bǔ),而這個(gè)短暫的不一致也不會(huì)引發(fā)業(yè)務(wù)問題。
  • 同時(shí),業(yè)務(wù)系統(tǒng)依賴于這個(gè)日志寫入邏輯,如果這個(gè)庫不可寫,會(huì)導(dǎo)致線上的業(yè)務(wù)操作無法執(zhí)行。

這時(shí)候,你可能就需要選擇先強(qiáng)行切換,事后再補(bǔ)數(shù)據(jù)的策略。

當(dāng)然,事后復(fù)盤的時(shí)候,我們想到了一個(gè)改進(jìn)措施就是,讓業(yè)務(wù)邏輯不要依賴于這類日志的寫入。也就是說,日志寫入這個(gè)邏輯模塊應(yīng)該可以降級(jí),比如寫到本地文件,或者寫到另外一個(gè)臨時(shí)庫里面。

這樣的話,這種場(chǎng)景就又可以使用可靠性優(yōu)先策略了。

接下來我們?cè)倏纯矗?strong>按照可靠性優(yōu)先的思路,異常切換會(huì)是什么效果?

假設(shè),主庫A和備庫B間的主備延遲是30分鐘,這時(shí)候主庫A掉電了,HA系統(tǒng)要切換B作為主庫。我們?cè)谥鲃?dòng)切換的時(shí)候,可以等到主備延遲小于5秒的時(shí)候再啟動(dòng)切換,但這時(shí)候已經(jīng)別無選擇了。

圖5 可靠性優(yōu)先策略,主庫不可用

采用可靠性優(yōu)先策略的話,你就必須得等到備庫B的seconds_behind_master=0之后,才能切換。但現(xiàn)在的情況比剛剛更嚴(yán)重,并不是系統(tǒng)只讀、不可寫的問題了,而是系統(tǒng)處于完全不可用的狀態(tài)。因?yàn)?,主庫A掉電后,我們的連接還沒有切到備庫B。

你可能會(huì)問,那能不能直接切換到備庫B,但是保持B只讀呢?

這樣也不行。

因?yàn)?,這段時(shí)間內(nèi),中轉(zhuǎn)日志還沒有應(yīng)用完成,如果直接發(fā)起主備切換,客戶端查詢看不到之前執(zhí)行完成的事務(wù),會(huì)認(rèn)為有“數(shù)據(jù)丟失”。

雖然隨著中轉(zhuǎn)日志的繼續(xù)應(yīng)用,這些數(shù)據(jù)會(huì)恢復(fù)回來,但是對(duì)于一些業(yè)務(wù)來說,查詢到“暫時(shí)丟失數(shù)據(jù)的狀態(tài)”也是不能被接受的。

聊到這里你就知道了,在滿足數(shù)據(jù)可靠性的前提下,MySQL高可用系統(tǒng)的可用性,是依賴于主備延遲的。延遲的時(shí)間越小,在主庫故障的時(shí)候,服務(wù)恢復(fù)需要的時(shí)間就越短,可用性就越高。

小結(jié)

今天這篇文章,我先和你介紹了MySQL高可用系統(tǒng)的基礎(chǔ),就是主備切換邏輯。緊接著,我又和你討論了幾種會(huì)導(dǎo)致主備延遲的情況,以及相應(yīng)的改進(jìn)方向。

然后,由于主備延遲的存在,切換策略就有不同的選擇。所以,我又和你一起分析了可靠性優(yōu)先和可用性優(yōu)先策略的區(qū)別。

在實(shí)際的應(yīng)用中,我更建議使用可靠性優(yōu)先的策略。畢竟保證數(shù)據(jù)準(zhǔn)確,應(yīng)該是數(shù)據(jù)庫服務(wù)的底線。在這個(gè)基礎(chǔ)上,通過減少主備延遲,提升系統(tǒng)的可用性。

最后,我給你留下一個(gè)思考題吧。

一般現(xiàn)在的數(shù)據(jù)庫運(yùn)維系統(tǒng)都有備庫延遲監(jiān)控,其實(shí)就是在備庫上執(zhí)行 show slave status,采集seconds_behind_master的值。

假設(shè),現(xiàn)在你看到你維護(hù)的一個(gè)備庫,它的延遲監(jiān)控的圖像類似圖6,是一個(gè)45°斜向上的線段,你覺得可能是什么原因?qū)е履兀磕阌謺?huì)怎么去確認(rèn)這個(gè)原因呢?

圖6 備庫延遲
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
數(shù)據(jù)庫容災(zāi)技術(shù)
mysql高可用架構(gòu)
MySQL主從復(fù)制什么原因會(huì)造成不一致,如何預(yù)防及解決?
踩坑無數(shù),美團(tuán)點(diǎn)評(píng)高可用數(shù)據(jù)庫架構(gòu)演進(jìn)
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服