業務零影響!如何在Online環境中巧用MySQL傳統複製技術

這篇文章我並不會介紹如何部署一個MySQL複製環境或keepalived+雙主環境,因爲此類安裝搭建的文章已經很多,大家也很熟悉。在這篇文章裏,我主要是介紹MySQL複製技術在Online【在線業務系統】環境裏如何進行架構上的調整,同時這些調整對在線業務系統的影響又是儘可能的小甚至是零影響。希望大家能有所收穫。

 

1MySQL複製中的監控管理

大家都知道,MySQL複製(不論是經典傳統複製還是5.6新引入的GTID複製)都是以io_thread和sql_thread這兩個核心線程爲基礎來實現的。(關於複製的原理在這篇文章我就不過多闡述,有興趣可以關注我以後的文章)

那我們在實際工作中需要關心以下幾個問題:

顯然,在Slave裏的show slave status\G給我們提供了足夠的信息來確認以上的問題。(雙主環境,兩個複製節點均有show slave status\G信息)

show slave status\G中首先要看的信息是:

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

Slave_IO_Running代表io_thread是否正常工作,Slave_SQL_Running代表sql_thread是否正常工作。如果有出現No,那你的複製環境應該就需要報警了。

但僅僅只關注這兩個指標還遠遠不夠,show slave status\G輸出信息裏我們還需要關注的值是:Seconds_Behind_Master【單位是秒】。

Seconds_behind_master = 0 表示沒有延遲, >0表示有延遲,當爲的時候,表示複製可能出錯了。

在實際工作中,我發現很多DBA朋友通常都只根據Seconds_Behind_Master的值判斷Slave是否存在延遲,這在部分情況裏尚可接受,但並不夠準確。特別是業務高併發的系統裏,我更不建議你使用Seconds_Behind_Master來作爲判定複製延遲的標準。

也就是說,Seconds_Behind_Master並不能非常準確地體現複製延遲,我們還需要考慮更多的因素。

真正來準確判斷Slave是否存在延遲,我們應該從複製的binlog文件名和binlog位置是否一致來入手。

我們知道,show slave status\G的輸出結果中:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

大多數時候,可以通過io_thread 和sql_thread執行的位置進行對比,來確認是不是存在延遲。(因爲在大多數時候,io_thread很少會存在延遲,一般都是sql_thread存在延遲,這種比較方法的前提是我們可以把io_thread的執行位置看作跟主庫show master status的位置一致的)

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

當show slave status\G輸出的這幾個指標信息滿足上面的條件,我們則可以認爲複製不存在延遲,是實時同步完成的。

如果你對io_thread的延遲也存在擔憂【比如複製環境的網絡不好等因素】,更嚴謹的思路是下面這樣:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

具體實現思路是:

在第三方監控節點上,對MASTER和SLAVE同時發起SHOW BINARY LOGS【或者SHOW MASTER STATUS】和SHOW SLAVE STATUS\G的請求,然後按照上面的公式去判斷是否存在差異。

當然,這麼做起來的話,腳本實現相對麻煩,而且對第三方監控節點的網絡要求也非常高,同時,由於io_thread一般不會是瓶頸,所以在做腳本監控的時候,不會這麼幹。大多數時候按照我之前說的做法來監控複製延遲就已經足夠了:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

還有一種監控MySQL複製的方式是:通過維護一個監控表來判定複製延遲。

可以在MASTER上維護一個監控表,一般只有兩個字段(id和time),存儲這最新最新時間戳(高版本MySQL可以採用event_scheduler來更新,低版本可以用Linux cron結合自動循環腳本來更新),然後在SLAVE上讀取該字段的時間,只要MASTER和SLAVE的系統時間【NTP是必須的】一致,即可快速知道SLAVE和MASTER延遲差了多少。

舉例:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

這種監控方式稱爲update心跳。

另外注意,在高併發的系統下,這個時間戳需要細化到毫秒,否則哪怕時間一致,也是有可能會延遲數個binlog event的。

以上是MySQL傳統複製中在監控這一塊需要我們注意的一些地方,只要我們把思路理清,編寫一個MySQL複製的監控腳本應該是順理成章的事情。(用python、perl、shell或其他語言寫一個都應該問題不大)

那接下來,進入我們的正題。

 

2MySQL複製中Online(在線)架構的調整

首先我要強調下在線架構,因爲在一個已經離線(停機)的環境裏做架構調整並沒有太多技術含量。

在線架構,就是已經投入在使用的架構,已經面向業務用戶開放的系統架構。

在線架構,意味着數據每份每秒都在不停得寫入,show master status的log_file和log_pos,時刻都在進行變化。數據是不會靜止的,這就是在線架構。

這和公司裏的開發環境或測試環境不同,是在線線上的環境。

那我們下面說的複製架構調整,就是必須在Online這個背景下來做調整的。

另外,下面的介紹基於MySQL傳統複製,如果是使用MySQL5.6以後的GTID複製,你可以不用太關心下面的內容。 GTID複製在運維上比傳統複製方便了很多,有關GTID複製的內容會在以後的文章裏講解。

第一個實戰:如何在一個在線架構的複製環境裏引入VIP

假設我們已經在線的一個簡單的主從環境如下:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

應用的連接全部都是連在192.168.1.10的master上進行訪問的。

我們這裏想通過實現一次Online(在線)切換,來實現MySQL的內存擴容,因爲Slave的內存是32G。

按照目前的架構,在做切換完成後,我們得需要修改應用服務器的IP地址爲192.168.1.11,那這個操作肯定會影響業務系統使用,無法滿足在線架構系統的要求。

更好的解決方案是給目前的複製環境引入一個虛擬IP(VIP),通過VIP來實現切換,這樣在線切換起來的影響會小很多。

假設我們申請的VIP是:192.168.1.20

那我們把這個VIP先綁到master上:

master的主機節點上會有兩個IP:

192.168.1.10【Real_IP】

192.168.1.20【VIP】 這個是我們手工綁上的。

那我們現在要考慮的是在線把應用服務器的數據庫地址連接改192.168.1.20:3306 ,這個影響有多大?

實際的情況取決與你前端應用服務器的架構了,如果你的前端應用服務器只有一臺,那肯定還是有影響的,但大多數時候,前端的應用服務器也是集羣架構,都是能實現無狀態的。那其實只要前端應用服務器的結構稍微合理,這個引入VIP的操作是0影響的。

引入VIP後【實際上就是在node1上綁定一個VIP】,應用服務器就都通過VIP連接到數據庫了,架構如下:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

這裏的切換,我們不引入任何第三方的組件,什麼keepalived,MHA都不考慮,我們就是自己寫腳本來做切換。

我們來看下,手動腳本切換的思路,前提還是我們說的在線架構:

1. 前置準備

master【node1】 vip unbind【VIP解綁】,同時檢查原來的master是否還有連接及連接的處理,如果還存在連接,要考慮把這些連接都幹掉:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

然後source /tmp/1.sql 就行了。

master上幹掉殘餘連接後,前置準備還要注意下slave的read_only問題,如果slave設置了read_only,記得取消。

master幹掉連接後,可以短暫的實現數據靜止。

2. 接管VIP之前需要做複製一致性檢查

這個複製一致性檢查很簡單,我們之前講的老辦法:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

確認複製pos都對上了,node2才能接管VIP,這裏在腳本里面最好把判斷一致性通過的log_file和log_pos記錄下來。

3. node2上綁定VIP

slave vip bind

這樣就完成了整個的切換流程。

總結來說,非常簡單:

  1. 複製環境引入VIP,修改應用服務器連接數據庫地址爲VIP

  2. 解綁原master上的VIP

  3. 幹掉原master上的所有應用連接

  4. 檢查同步一致性

  5. slave上綁定vip

以上這些動作,如果腳本準備充分,執行腳本一般3-5秒就可以搞定了。

雖然是在線架構,3-5秒左右的數據庫短暫影響,在業務低峯期應用基本是無感知的【切換我們還是需要錯峯來執行】,絕對能滿足在線架構系統的要求。

另外的一個注意點就是要確保檢查同步都完成了,同步沒完成的話,是還要花一點時間等待直到完成爲止。

那成功切換後,現在VIP綁定在了node2上【新的master】,那node1重新要從node2上同步數據,node1變爲slave,這裏分情況討論:

  • 如果node1和node2之前做的是雙master架構,那最簡單,不用多管【實際架構中雙master也是最多用的,就是切換後維護方便】

  • 如果node1和node2只做了主從架構,那還得在之前的腳本里【檢查同步是否完成這1步中】記錄下log_file和log_pos,在node1【新的slave】上重新做一次change master to master_log_file=XXX,master_log_pos=XXX,然後在node2【新的master】上reset slave all,清空原來的show slave status\G信息

第二個實戰:在線系統環境中調整爲MySQL級聯複製架構

假設,現有的架構如下:

目前的架構是:

A->B(單向複製)

A->C(單向複製)

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

如何把上面的架構調整爲:A->B->C 的級聯複製架構呢?

同樣,我們需要在線實現,不能對業務有太大影響【假設業務都是在master上執行,沒有做讀寫分離拆分】

這裏的思路是:

  • 不去動master,因爲業務都在master上【這樣可以保證對master的0影響,滿足在線業務不間斷的需求】。而是想辦法讓slave1和slave2停在一個相同的pos位置,只要slave1和slave2靜止下來,我們就可以很方便地進行架構調整了:

  • 實現目的:讓slave1(B)和slave2(C)停在相同的pos位置上,數據靜止下來。

操作步驟:

1.(master)A上執行 : create table biaobiao(id int);

2.(slave)B和C上執行: drop table biaobiao;

3.(master)A上執行 : drop table biaobiao;

上面的操作會導致B、C上同步報錯,都報錯後【sql thread報錯】,我們就可以開始比對sql_thread執行的位置了(實際目的就是人爲地去讓B和C停在同一個位置上)

4.slave1(B)和slave2(C)上show slave status\G 發現報錯,同時檢查各個複製點的位置是否相等(此時Slave上的sql_thread應該都停止工作了):

檢查複製點位置的公式如下:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

檢查後公式都相等,就代表B和C已經停到同一個複製位置了。B和C的數據此時應該是完全一致。

此時B和C上的relay_master_log_file和exec_master_log_pos 都不會變化了。

一旦讓B和C停在了同一個位置,那接下來的事情就好辦了。

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

此時,C就變成了B的Slave

完成了架構調整 A->B->C

如果腳本來做,一定要在B上多做幾次show master status,確保輸出不會變化,靜止下來,同時B和C的pos要相等:

B節點: show master status;

sleep(10);

B節點: show master status;

因爲此時sql thread已經報錯卡住了【sql_thread:no 、io_thread:yes】,因此前後的show master status在B上肯定是一致的。

B是靜止的,C也是靜止的,然後B和C的exec_master_log_pos相等。

接下來還沒完,還需要恢復A->B的複製,A到B的複製sql thread人爲搞斷了,還得恢復:

在B上跳過複製錯誤,在B上執行

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

因爲,這個複製錯誤是我們人工模擬出來的,是有把握的,所以才能跳過。任何沒有把握的複製錯誤,都是不能輕易跳過的。

8.最後全部恢復後,進行一把測試,測試下新的架構是否通的。有條件再效驗下數據。

這裏,完成了我們需求的複製在線架構調整。

第三個實戰:雙master複製環境中的運維管理

實際上,業務規模稍微大一點的公司,在做MySQL的時候都會搭建雙master【主主】架構。相較於單向的主從複製,雙master架構在運維管理上相對更方便,省事。因爲單向的主從結構,在發生主從切換後,還得在原來舊的master上再搞一次change master to ,同時在新的master上執行reset slave all;

這就比雙master複製架構稍顯繁瑣了。雙master架構在發生切換後,撒事不用做,僅漂移VIP就行了【雙master和keeaplived這類HA組件結合起來也能非常方便得實現自動切換】。

那如果僅僅就是兩個節點的雙master環境,大家需要注意的就是在生產環境保持其中一個節點來進行業務數據寫入就好了。

那爲什麼明明雙master是雙向複製,照理兩個節點都可以雙向同時寫入數據,我這裏卻只建議大家單邊寫入呢?單邊寫是不是有點浪費資源呢?

也許有朋友會答到MySQL裏面有兩個不錯的參數:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

我只要在雙master的兩個節點上分別把這兩個參數配置正確,就可以很好的解決雙寫衝突的問題,同時也最大化的利用了服務器資源,減緩了單臺的寫入壓力。

的確,利用auto_increment_increment和auto_increment_offset能夠解決部分的寫入衝突問題,但是僅僅只能解決insert的衝突,但遇到是針對同一行數據的update和delete操作,配置這兩個參數還是搞不定的。

試想一下,在雙master的兩個節點上同時發起下面這條SQL語句【假設在業務高峯期併發度高的時候】:

update tb set col1=xxx where id = 1;

顯然會引起寫入衝突和鎖競爭,就無疑就給我們挖坑了。

因此,auto_increment_increment和auto_increment_offset參數其實只能解決insert的寫入衝突,而對同一行的update或delete衝突卻無法解決。

也許你還會說,我們公司的業務拆分做得不錯,在node1我們只會寫A表,在node2上只會寫B表,不可能在兩個節點上發生update同一行數據的問題。這聽起來確實是一個不錯的最終解決寫入衝突的方案,但你依然可能遇到另外一個問題:

如果啓用雙節點雙邊寫,其中一個節點不幸掛掉的話,切換另外一個節點能順利接管嗎?你會面臨性能瓶頸的問題,在大多數時候,你用了兩個節點的資源來承擔讀寫壓力,當突然變成一個節點來承擔所有的讀寫壓力時候,這個節點的性能能抗得住嗎?

這跟Oracle RAC的架構設計有點類似,兩個節點同時提供服務的話,你還得考慮很多性能上的問題,每個節點都要做性能的預留,不然其中一個節點掛了,另外一個節點就算你能故障切換過來,性能扛不住的話也是一點意義沒有。

因此,在雙master複製環境中我建議大家用單節點抗業務就好了,另外一個節點就完全預留做爲故障切換使用,沒有必要用兩個節點來同時承擔業務壓力,因爲這可能會給我們在運維管理上挖坑。

這是雙master架構裏只有兩個節點的運維管理注意點,但很多時候,我們還會爲雙master環境引入一個或多個slave來分擔讀(read)的壓力,或者用來做一些經分統計和統計報表用,就像下面這樣:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

上面這種架構纔是我們實際運維管理工作中最常見的架構。

在上圖裏面:

  • M1和M2互爲雙master複製環境,而S1是一個單獨的slave。

  • R_IP代表每個服務器的real_ip(真實IP),W_VIP代表虛擬的VIP,應用程序的所有寫入操作應該都是通過VIP來連接到數據庫,在上圖的架構裏W_VIP掛在了M1上,代表M1這個節點是主要用來抗應用業務的節點。而M2是完全爲了作爲故障切換(failover)的節點,S1是我們做統計報表的(分擔部分讀壓力)的節點。

在這類架構中,我們要理清的第一個問題是:

S1是掛在M1上,還是掛在M2上,或者說是掛在W_VIP上呢?

  • 很明顯,傳統複製模型裏掛在W_VIP上是不行的,原因是: m1和m2 binlog filename 、binlog position 完全有可能不一樣。(M1和M2的 show master status出來的結果是不同的),如果是GTID複製的話,原理上可以掛在W_VIP上,但即使是GTID,一般也不會這麼做。

另外,如果把S1掛在M1這個抗業務的節點上,那當M1節點不幸掛掉,在傳統複製原理下,S1和M2就很難聯繫起來了。、

因此,正確答案是:S1必須掛在不是抗業務的那個雙master節點上,即掛在圖裏的M2這個節點,這樣做的好處是當M1不幸掛掉,M2和S1的複製不會受到任何影響。

這是我們設計架構時的注意點。

另外一個重要的注意點是,當M1掛掉後,W_VIP會漂移到M2節點上,保證應用程序繼續能正常連接數據庫,像下圖這樣:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

那當M1掛掉後,我們把M1修復好後,M1還會繼續加入到複製集羣架構裏,像下面這樣:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

此時的架構變爲了:

M2->S

M2<->M1

但如果是這樣的架構,就和我們剛纔提到的設計依據:

  • “S1必須掛在不是抗業務的那個雙master節點上”相違背了,這裏明顯S1是掛在了抗業務的M2架構上,是不正確的,我們還需要調整S1在複製架構中的位置,把S1掛到M1下才行。

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

我們還需要想辦法從上圖左邊的架構調整爲上圖右邊的架構,同樣,這個調整我們肯定也需要在Online在線業務的背景下去完成。

那這個調整其實跟我們在第二個實戰裏講的案例非常類似了。

原來的架構是:

M2<->M1(雙向複製)

M2->S1(單向複製)

現在要把架構調成爲:M2<->M1->S1(級聯複製)

要實現這個調整的辦法,我們就可以完全照着第二個實戰裏說的方法來做【這裏請大家回到前面的內容,再仔細閱讀一遍】。

基本的思路依然是讓保持對M2的0影響,而通過人爲的模擬複製錯誤讓M1和S1停在相同的複製點位上。

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

這裏稍微不同的就是因爲M2和M1互爲主主,M1上的人爲模擬操作也會同步到M2上,所以在M1上做人爲模擬操作的時候,要記得臨時禁止寫binlog,免得把M1上做的人爲模擬操作也同步到M2上了。

後面的步驟和我們在第二個實戰裏面講的步驟完全一致,照搬就行了。我就不贅述了。

完成以上的調整,纔算一個雙master+slave複製架構的切換完成。

第四個實戰: 在線系統環境把級聯複製架構再調整回一主多從的架構

原來的架構是:A->B->C【級聯複製】

現在要把架構調成爲:

A->B

A->C 【一主兩從】

同樣,A節點是抗應用業務的節點。

其實經過我們之前的幾個案例,這個案例是很簡單的了,這個我就簡單提下:

對上面的這類需求,在B節點上stop slave就行了,stop後等待會,B和C的數據應該就能一致了:

檢查公式:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

滿足以上公式,代表B節點和C節點的同步是一致的了。

接下來在C上進行change master的修改,change master到A上,在C節點的MySQL上操作:

業務零影響!如何在Online環境中巧用MySQL傳統複製技術

注意,這裏要取B節點上show slave status\G的relay_master_log_file , exec_master_log_pos

start slave;

最後回到B節點的MySQL上操作:

start slave;

整個架構調整完成。

總結

以上是一些工作中的總結,重點在於給大家提供一種思路,希望大家能在這個基礎上繼續擴展思維。

有了清晰的思路,編寫一些MySQL複製運維中的管理腳本也並不是難事。

如果大家在編寫複製管理的腳本中遇到任何問題,也可以隨時找我交流。

另外,每個公司的業務對在線【Online】架構的要求可能是不同的,有的公司業務在Online環境裏也能容忍在特定時間的3-5秒甚至更長時間的業務暫停寫入,而有的公司業務卻是0容忍,我們應該緊密結合業務上的需求,以需求爲導向,才能更好的完成MySQL複製管理工作。

當然,隨着MySQL版本的不斷髮展,比如:MySQL5.6引入的GTID複製,MySQL5.7引入的group commit和並行複製,這些新的技術也逐漸讓MySQL的複製運維管理工作變得更加得便捷,高效。

但是,不論技術如何發展和變化,掌握MySQL經典傳統複製的運維管理技巧仍然能幫我們搞定很多在線環境的管理需求。


轉自

業務零影響!如何在Online環境中巧用MySQL傳統複製技術_Mysql_數據庫-ITnose
http://www.itnose.net/detail/6525929.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章