踩坑無(wú)數(shù),美團(tuán)點(diǎn)評(píng)高可用數(shù)據(jù)庫(kù)架構(gòu)演進(jìn)
同時(shí),也和業(yè)界其他方案進(jìn)行綜合對(duì)比,了解業(yè)界在高可用方面的進(jìn)展和未來(lái)我們的一些規(guī)劃和展望。
MMM
在 2015 年之前,美團(tuán)點(diǎn)評(píng)(點(diǎn)評(píng)側(cè))長(zhǎng)期使用 MMM(Master-Master replication manager for MySQL)做數(shù)據(jù)庫(kù)高可用。
因此我們積累了比較多的經(jīng)驗(yàn),但也踩了不少坑,可以說(shuō) MMM 在公司數(shù)據(jù)庫(kù)高速發(fā)展過(guò)程中起到了很大的作用。
MMM 的架構(gòu)如下:
如上圖所示,整個(gè) MySQL 集群提供 1 個(gè)寫 VIP(Virtual IP)和 N(N>=1)個(gè)讀 VIP 的對(duì)外服務(wù)。
每個(gè) MySQL 節(jié)點(diǎn)均部署有一個(gè) Agent(mmm-agent),mmm-agent 和 mmm-manager 保持通信狀態(tài),定期向 mmm-manager 上報(bào)當(dāng)前 MySQL 節(jié)點(diǎn)的存活情況(這里稱之為心跳)。
當(dāng) mmm-manager 連續(xù)多次無(wú)法收到 mmm-agent 的心跳消息時(shí),會(huì)進(jìn)行切換操作。
mmm-manager 分兩種情況處理出現(xiàn)的異常:
- 出現(xiàn)異常的是從節(jié)點(diǎn),mmm-manager 會(huì)嘗試摘掉該從節(jié)點(diǎn)的讀 VIP,并將該讀 VIP 漂移到其他存活的節(jié)點(diǎn)上,通過(guò)這種方式實(shí)現(xiàn)從庫(kù)的高可用。
- 出現(xiàn)異常的是主節(jié)點(diǎn),如果當(dāng)時(shí)節(jié)點(diǎn)還沒完全掛,只是響應(yīng)超時(shí),則嘗試將 Dead Master 加上全局鎖(flush tables with read lock),在從節(jié)點(diǎn)中選擇一個(gè)候選主節(jié)點(diǎn)作為新的主節(jié)點(diǎn),進(jìn)行數(shù)據(jù)補(bǔ)齊。
數(shù)據(jù)補(bǔ)齊之后,摘掉 Dead Master 的寫 VIP,并嘗試加到新的主節(jié)點(diǎn)上。將其他存活的節(jié)點(diǎn)進(jìn)行數(shù)據(jù)補(bǔ)齊,并重新掛載在新的主節(jié)點(diǎn)上。
主庫(kù)發(fā)生故障后,整個(gè)集群狀態(tài)變化如下:
mmm-manager 檢測(cè)到 master1 發(fā)生了故障,對(duì)數(shù)據(jù)進(jìn)行補(bǔ)齊之后,將寫 VIP 漂移到了 master2 上,應(yīng)用寫操作在新的節(jié)點(diǎn)上繼續(xù)進(jìn)行。
然而,MMM 架構(gòu)存在如下問(wèn)題:
- VIP 的數(shù)量過(guò)多,管理困難(曾經(jīng)有一個(gè)集群是 1 主 6 從,共計(jì) 7 個(gè) VIP)。某些情況下會(huì)導(dǎo)致集群大部分 VIP 同時(shí)丟失,很難分清節(jié)點(diǎn)上之前使用的是哪個(gè) VIP。
- mmm-agent 過(guò)度敏感,容易導(dǎo)致 VIP 丟失。同時(shí) mmm-agent 自身由于沒有高可用,一旦掛掉,會(huì)造成 mmm-manager 誤判,誤認(rèn)為 MySQL 節(jié)點(diǎn)異常。
- mmm-manager 存在單點(diǎn),一旦由于某些原因掛掉,整個(gè)集群就失去了高可用。
- VIP 需要使用 ARP 協(xié)議,跨網(wǎng)段、跨機(jī)房的高可用基本無(wú)法實(shí)現(xiàn),保障能力有限。
同時(shí),MMM 是 Google 技術(shù)團(tuán)隊(duì)開發(fā)的一款比較老的高可用產(chǎn)品,在業(yè)內(nèi)使用的并不多,社區(qū)也不活躍,Google 很早就不再維護(hù) MMM 的代碼分支。
我們?cè)谑褂眠^(guò)程中發(fā)現(xiàn)大量 Bug,部分 Bug 我們做了修改,并提交到開源社區(qū)。
MHA
針對(duì)于此,從 2015 年開始,美團(tuán)點(diǎn)評(píng)對(duì) MySQL 高可用架構(gòu)進(jìn)行了改進(jìn),全部更新為 MHA,很大程度上解決了之前 MMM 遇到的各種問(wèn)題。
MHA(MySQL Master High Availability)是由 Facebook 工程師 Yoshinori Matsunobu 開發(fā)的一款 MySQL 高可用軟件,從名字就可以看出,MHA 只負(fù)責(zé) MySQL 主庫(kù)的高可用。
當(dāng)主庫(kù)發(fā)生故障時(shí),MHA 會(huì)選擇一個(gè)數(shù)據(jù)最接近原主庫(kù)的候選主節(jié)點(diǎn)(這里只有一個(gè)從節(jié)點(diǎn),所以該從節(jié)點(diǎn)即為候選主節(jié)點(diǎn))作為新的主節(jié)點(diǎn),并補(bǔ)齊和之前 Dead Master 差異的 Binlog。數(shù)據(jù)補(bǔ)齊之后,即將寫 VIP 漂移到新主庫(kù)上。
整個(gè) MHA 的架構(gòu)如下(為簡(jiǎn)單起見,只描述一主一從):
這里我們對(duì) MHA 做了一些優(yōu)化,避免一些腦裂問(wèn)題。
比如 DB 服務(wù)器的上聯(lián)交換機(jī)出現(xiàn)了抖動(dòng),導(dǎo)致主庫(kù)無(wú)法訪問(wèn),被管理節(jié)點(diǎn)判定為故障,觸發(fā) MHA 切換,VIP 被漂到了新主庫(kù)上。
隨后交換機(jī)恢復(fù),主庫(kù)可被訪問(wèn),但由于 VIP 并沒有從主庫(kù)上摘除,因此 2 臺(tái)機(jī)器同時(shí)擁有 VIP,會(huì)產(chǎn)生腦裂。
我們對(duì) MHA Manager 加入了向同機(jī)架上其他物理機(jī)的探測(cè),通過(guò)對(duì)比更多的信息來(lái)判斷是網(wǎng)絡(luò)故障還是單機(jī)故障。
MHA+Zebra(DAL)
Zebra(斑馬)是美團(tuán)點(diǎn)評(píng)基礎(chǔ)架構(gòu)團(tuán)隊(duì)開發(fā)的一個(gè) Java 數(shù)據(jù)庫(kù)訪問(wèn)中間件。
它是在 c3p0 基礎(chǔ)上包裝的美團(tuán)點(diǎn)評(píng)內(nèi)部使用的動(dòng)態(tài)數(shù)據(jù)源,包括讀寫分離、分庫(kù)分表、SQL 流控等非常強(qiáng)的功能,它和 MHA 配合,成為了 MySQL 數(shù)據(jù)庫(kù)高可用的重要一環(huán)。
如下是 MHA+Zebra 配合的整體架構(gòu):
以主庫(kù)發(fā)生故障為例,處理邏輯有如下兩種方式:
- 當(dāng) MHA 切換完成之后,主動(dòng)發(fā)送消息給 Zebra monitor,Zebra monitor 更新 ZooKeeper 的配置,將主庫(kù)上配置的讀流量標(biāo)記為下線狀態(tài)。
- Zebra monitor 每隔一段時(shí)間(10s ~ 40s)檢測(cè)集群中節(jié)點(diǎn)的健康狀況,一旦發(fā)現(xiàn)某個(gè)節(jié)點(diǎn)出現(xiàn)了問(wèn)題,及時(shí)刷新 ZooKeeper 中的配置,將該節(jié)點(diǎn)標(biāo)記為下線。
一旦節(jié)點(diǎn)變更完成,客戶端監(jiān)聽到節(jié)點(diǎn)發(fā)生了變更,會(huì)立即使用新的配置重建連接,而老的連接會(huì)逐步關(guān)閉。
整個(gè)集群故障切換的過(guò)程如下(僅描述 Zebra monitor 主動(dòng)探測(cè)的情況,第一種 MHA 通知請(qǐng)自行腦補(bǔ)^_^)。
由于該切換過(guò)程還是借助于 VIP 漂移,導(dǎo)致只能在同網(wǎng)段或者說(shuō)同個(gè)二層交換機(jī)下進(jìn)行,無(wú)法做到跨網(wǎng)段或者跨機(jī)房的高可用。
為解決這個(gè)問(wèn)題,我們對(duì) MHA 進(jìn)行了二次開發(fā),將 MHA 添加 VIP 的操作去掉,切換完之后通知 Zebra monitor 去重新調(diào)整節(jié)點(diǎn)的讀寫信息(將 Write 調(diào)整為 new master 的實(shí) IP,將 Dead Master 的讀流量摘除)。
整個(gè)切換就完全去 VIP 化,做到跨網(wǎng)段、甚至跨機(jī)房切換,徹底解決之前高可用僅局限于同網(wǎng)段的問(wèn)題。
上述切換過(guò)程就變成了如下圖:
然而,這種方式中的 MHA 管理節(jié)點(diǎn)是單點(diǎn),在網(wǎng)絡(luò)故障或者機(jī)器宕機(jī)情況下依然存在風(fēng)險(xiǎn)。
同時(shí),由于 Master-Slave 之間是基于 Binlog 的異步復(fù)制,也就導(dǎo)致了主庫(kù)機(jī)器宕機(jī)或者主庫(kù)無(wú)法訪問(wèn)時(shí),MHA 切換過(guò)程中可能導(dǎo)致數(shù)據(jù)丟失。
另外,當(dāng) Master-Slave 延遲太大時(shí),也會(huì)給數(shù)據(jù)補(bǔ)齊這一操作帶來(lái)額外的時(shí)間開銷。
Proxy
除了 Zebra 中間件,美團(tuán)點(diǎn)評(píng)還有一套基于 Proxy 的中間件和 MHA 一起配合使用。
當(dāng) MHA 切換后,主動(dòng)通知 Proxy 來(lái)進(jìn)行讀寫流量調(diào)整,Proxy 相比 Zebra 更加靈活,同時(shí)也能覆蓋非 Java 應(yīng)用場(chǎng)景。
缺點(diǎn)就是訪問(wèn)鏈路多了一層,對(duì)應(yīng)的 Response Time 和故障率也有一定增加。
未來(lái)架構(gòu)設(shè)想
MHA 架構(gòu)依然存在如下兩個(gè)問(wèn)題:
- 管理節(jié)點(diǎn)單點(diǎn)
- MySQL 異步復(fù)制中的數(shù)據(jù)丟失
針對(duì)于此,我們?cè)诓糠趾诵臉I(yè)務(wù)上使用 Semi-Sync,可以保證 95% 以上場(chǎng)景下數(shù)據(jù)不丟失(依然存在一些極端情況下無(wú)法保障數(shù)據(jù)的強(qiáng)一致性)。
另外,高可用使用分布式的 Agent,在某個(gè)節(jié)點(diǎn)發(fā)生故障后,通過(guò)一定的選舉協(xié)議來(lái)選擇新的 Master,從而解決了 MHA Manager 的單點(diǎn)問(wèn)題。
針對(duì)上述問(wèn)題,我們研究了業(yè)界的一些領(lǐng)先的做法,簡(jiǎn)單描述如下。
主從同步數(shù)據(jù)丟失
針對(duì)主從同步的數(shù)據(jù)丟失,一種做法是創(chuàng)建一個(gè) Binlog Server,該 Server 模擬 Slave 接受 Binlog 日志,主庫(kù)每次的數(shù)據(jù)寫入都需要接收到 Binlog Server 的 ACK 應(yīng)答,才認(rèn)為寫入成功。
Binlog Server 可以部署在就近的物理節(jié)點(diǎn)上,從而保證每次數(shù)據(jù)寫入都能快速落地到 Binlog Server。
在發(fā)生故障時(shí),只需要從 Binlog Server 拉取數(shù)據(jù)即可保證數(shù)據(jù)不丟失。
分布式 Agent 高可用
針對(duì) MHA 管理節(jié)點(diǎn)單點(diǎn)問(wèn)題,一種做法是讓 MySQL 數(shù)據(jù)庫(kù)集群中每個(gè)節(jié)點(diǎn)部署 Agent,當(dāng)發(fā)生故障時(shí),每個(gè) Agent 均參與選舉投票,選舉出合適的 Slave 作為新的主庫(kù),防止只通過(guò) Manager 來(lái)切換,去除 MHA 單點(diǎn)。
整個(gè)架構(gòu)如下圖所示:
MGB 結(jié)合中間件高可用
上述方式某種程度上解決了之前的問(wèn)題,但是 Agent 和 Binlog Server 卻是新引入的風(fēng)險(xiǎn),同時(shí) Binlog Server 的存在,也帶來(lái)了響應(yīng)時(shí)間上的額外開銷。
有沒有一種方式,能夠去除 Binlog Server 和 Agent,又能保證數(shù)據(jù)不丟失呢 ?答案當(dāng)然是有的。
最近幾年,MySQL 社區(qū)關(guān)于分布式協(xié)議 Raft 和 Paxos 非常火,社區(qū)也推出了基于 Paxos 的 MGR 版本的 MySQL,通過(guò) Paxos 將一致性和切換過(guò)程下推到數(shù)據(jù)庫(kù)內(nèi)部,向上層屏蔽了切換細(xì)節(jié)。
架構(gòu)如下(以 MGR 的 single-primary 為例):
當(dāng)數(shù)據(jù)庫(kù)發(fā)生故障時(shí),MySQL 內(nèi)部自己進(jìn)行切換。切換完成后將 topo 結(jié)構(gòu)推送給 Zebra monitor,Zebra monitor 進(jìn)行相應(yīng)的讀寫流量變更。
不過(guò),該架構(gòu)存在與 Binlog Server 同樣的需要回復(fù)確認(rèn)問(wèn)題,就是每次主庫(kù)數(shù)據(jù)寫入,都需要大多數(shù)節(jié)點(diǎn)回復(fù) ACK,該次寫入才算成功,存在一定的響應(yīng)時(shí)間開銷。
同時(shí),每個(gè) MGR 集群必須需要奇數(shù)個(gè)數(shù)(大于 1)的節(jié)點(diǎn),導(dǎo)致原先只需要一主一從兩臺(tái)機(jī)器,現(xiàn)在需要至少三臺(tái),帶來(lái)一定的資源浪費(fèi)。
但不管怎么說(shuō),MGR 的出現(xiàn)無(wú)疑是 MySQL 數(shù)據(jù)庫(kù)又一次偉大的創(chuàng)新。
結(jié)語(yǔ)
本文介紹了美團(tuán)點(diǎn)評(píng) MySQL 數(shù)據(jù)庫(kù)高可用架構(gòu)從 MMM 到 MHA+Zebra 以及 MHA+Proxy 的演進(jìn)歷程,同時(shí)也介紹了業(yè)界一些高可用的做法。
數(shù)據(jù)庫(kù)最近幾年的發(fā)展突飛猛進(jìn),數(shù)據(jù)庫(kù)的高可用設(shè)計(jì)上沒有完美的方案,只有不斷的突破和創(chuàng)新,我們也一直在這條路上探索更加優(yōu)秀的設(shè)計(jì)與更加完美的方案。
責(zé)任編輯:售電衡衡
-
碳中和戰(zhàn)略|趙英民副部長(zhǎng)致辭全文
2020-10-19碳中和,碳排放,趙英民 -
兩部門:推廣不停電作業(yè)技術(shù) 減少停電時(shí)間和停電次數(shù)
2020-09-28獲得電力,供電可靠性,供電企業(yè) -
國(guó)家發(fā)改委、國(guó)家能源局:推廣不停電作業(yè)技術(shù) 減少停電時(shí)間和停電次數(shù)
2020-09-28獲得電力,供電可靠性,供電企業(yè)
-
碳中和戰(zhàn)略|趙英民副部長(zhǎng)致辭全文
2020-10-19碳中和,碳排放,趙英民 -
深度報(bào)告 | 基于分類監(jiān)管與當(dāng)量協(xié)同的碳市場(chǎng)框架設(shè)計(jì)方案
2020-07-21碳市場(chǎng),碳排放,碳交易 -
碳市場(chǎng)讓重慶能源轉(zhuǎn)型與經(jīng)濟(jì)發(fā)展并進(jìn)
2020-07-21碳市場(chǎng),碳排放,重慶
-
兩部門:推廣不停電作業(yè)技術(shù) 減少停電時(shí)間和停電次數(shù)
2020-09-28獲得電力,供電可靠性,供電企業(yè) -
國(guó)家發(fā)改委、國(guó)家能源局:推廣不停電作業(yè)技術(shù) 減少停電時(shí)間和停電次數(shù)
2020-09-28獲得電力,供電可靠性,供電企業(yè) -
2020年二季度福建省統(tǒng)調(diào)燃煤電廠節(jié)能減排信息披露
2020-07-21火電環(huán)保,燃煤電廠,超低排放
-
四川“專線供電”身陷違法困境
2019-12-16專線供電 -
我國(guó)能源替代規(guī)范法律問(wèn)題研究(上)
2019-10-31能源替代規(guī)范法律 -
區(qū)域鏈結(jié)構(gòu)對(duì)于數(shù)據(jù)中心有什么影響?這個(gè)影響是好是壞呢!