為什么MySQL要升級組復(fù)制?一分鐘系列
之前發(fā)了《Galera,MySQL主從之外的另一種選擇》之后,很多朋友在評論里留言:
- “這不就是Oracle Rac嗎?”
- “這不就是MGR嗎?”
- …
思路比結(jié)論重要,為什么比是什么重要,今天就花1分鐘,說下這里面架構(gòu)演進(jìn)的思路。
畫外音:大家不想聽底層細(xì)節(jié),就不深入細(xì)節(jié)了。
最早的數(shù)據(jù)庫都是單機(jī)的,其最大的痛點是啥?
無法線性擴(kuò)展。
磁盤能力無法線性擴(kuò)展,內(nèi)存能力無法線性擴(kuò)展,計算能力無法線性擴(kuò)展。
如今,喜歡創(chuàng)造概念的架構(gòu)師們,把這種架構(gòu)稱為“Shared Everything”架構(gòu)。
如上圖所示,DISK/MEM/CPU 都耦合在一個DBMS進(jìn)程內(nèi),必須部署在一臺服務(wù)器上,完全處于競爭態(tài),無法線性擴(kuò)展,并行處理較差。
數(shù)據(jù)庫單機(jī)部署,就是典型的“Shared Everything”架構(gòu)。
如何來提升系統(tǒng)的并行能力呢?
最容易想到的,就是把無狀態(tài)的邏輯計算部分,從DBMS進(jìn)程內(nèi)拆分出來,做成可擴(kuò)展的微服務(wù)集群,實現(xiàn)“計算與存儲分離”。
如上圖所示:
(1)CPU邏輯計算拆分出了獨立的進(jìn)程,可以集群部署,能夠線程擴(kuò)展;
(2)DISK/MEM 仍耦合在一個進(jìn)程內(nèi),仍處于競爭態(tài),無法線性擴(kuò)展;
Oracle Rac,就是典型的“Shared Disk”架構(gòu),核心思路是“計算與存儲分離”。
存儲部分磁盤IO仍有集中的資源競爭,還有沒有進(jìn)一步的優(yōu)化空間呢?
最容易想到的,就是把數(shù)據(jù)打散,分布到不同的數(shù)據(jù)庫實例上,每部分?jǐn)?shù)據(jù)享有單獨的資源。
如上圖所示:
(1)把整體數(shù)據(jù)存儲分為了N份,每份之間沒有交集;
(2)每份數(shù)據(jù)的 DISK/MEM/CPU 都在一個DBMS進(jìn)程內(nèi),部署在一臺服務(wù)器上;
(3)每份數(shù)據(jù)的資源之間的沒有競爭;
沒錯,這就是“水平切分”,它是典型的”Shared Nothing”架構(gòu)。
對 Shared Everything/Disk/Nothing 這些高大上的名詞,進(jìn)一步認(rèn)識了不?
事情還沒完,水平切分存在什么問題呢?
水平切分雖然是一種可擴(kuò)展架構(gòu),能夠?qū)崿F(xiàn)線性擴(kuò)展資源,但它會使得調(diào)用方失去數(shù)據(jù)的全局視野,使得調(diào)用方能力受限:
(1)無法實現(xiàn)全局JOIN;
(2)無法實現(xiàn)全局排序;
(3)無法支持集函數(shù);
(4)原訪問一次DBMS的操作,需要調(diào)用多次;
(5)…
并把一些原本屬于DBMS職責(zé)的工作,轉(zhuǎn)嫁到調(diào)用方。
如何解決“線性擴(kuò)展能力”,同時又解決“失去全局視野”與“調(diào)用方能力受限”的問題呢?
最容易想到的方案是,數(shù)據(jù)庫主從集群,每份數(shù)據(jù)都進(jìn)行復(fù)制,每個實例都獨享 DISK/MEM/CPU資源,避免實例之間的資源競爭。
如上圖所示:
(1)把整體數(shù)據(jù)存儲分復(fù)制了N份,每份之間數(shù)據(jù)都一樣;
(2)每份數(shù)據(jù)的 DISK/MEM/CPU 都在一個DBMS進(jìn)程內(nèi),部署在一臺服務(wù)器上;
(3)每份數(shù)據(jù)的資源之間的沒有競爭;
理想很豐滿,現(xiàn)實很骨干,思路沒問題,但實際執(zhí)行“復(fù)制”的過程中,會碰到一些問題。
以MySQL為例,有3種常見的復(fù)制方式:
(1)異步復(fù)制
(2)半同步復(fù)制
(3)組復(fù)制
第一種,異步復(fù)制(Asynchronous Replication)
又叫主從復(fù)制(Primary-Secondary Replication),是互聯(lián)網(wǎng)公司用的最多的數(shù)據(jù)復(fù)制與數(shù)據(jù)庫集群化方法,它的思路是,從庫執(zhí)行串行化后的主庫事務(wù)。
其核心原理如上圖所示:
(1)第一條時間線:主庫時間線;
- 主庫執(zhí)行事務(wù)
- 主庫事務(wù)串行化binlog
- binlog同步給從庫
- 主庫事務(wù)提交完成
(2)第二條/第三條時間線:從庫時間線;
- 收到relay log
- 執(zhí)行和主庫一樣的事務(wù)
- 生成自己的binlog(還可以繼續(xù)二級從庫)
- 從庫事務(wù)提交完成
從這個時間線可以看到:
(1)主庫事務(wù)提交
(2)從庫事務(wù)執(zhí)行
是并行執(zhí)行的,主庫并不能保證從庫的事務(wù)一定執(zhí)行成功,甚至不能保證從庫一定收到相關(guān)的請求,這也是其稱作“異步復(fù)制”的原因。
第二種,半同步復(fù)制(Semi-synchronous Replication)
為了解決異步復(fù)制中“不能保證從庫一定收到請求”等問題,對異步復(fù)制做了升級。
其核心原理如上圖所示:
(1)第一條時間線:主庫時間線;
- 主庫執(zhí)行事務(wù)
- 主庫事務(wù)串行化binlog
- binlog同步給從庫
- 等從庫確認(rèn)收到請求,主庫事務(wù)才提交完成
(2)第二條/第三條時間線:從庫時間線;
- 收到relay log
- 執(zhí)行和主庫一樣的事務(wù),并給主庫一個確認(rèn)
- 生成自己的binlog(還可以繼續(xù)二級從庫)
- 從庫事務(wù)提交完成
從這個時間線可以看到:
(1)主庫收到從庫的ACK,才會提交;
(2)從庫收到請求后,事務(wù)提交前,會給主庫一個ACK;
半同步復(fù)制存在什么問題呢?
(1)主庫的性能,會受到較大的影響,事務(wù)提交之前,中間至少要等待2個主從之間的網(wǎng)絡(luò)TTL;
(2)從庫仍然有延時,主從之間數(shù)據(jù)仍然不一致;(3)主從角色有差異,主節(jié)點仍然是單點;
大數(shù)據(jù)量,高并發(fā)量的互聯(lián)網(wǎng)業(yè)務(wù),一般不使用“半同步復(fù)制”,更多的公司仍然使用“異步復(fù)制”的模式。
最后是MySQL5.7里,新提出的MySQL組復(fù)制。
第三種,組復(fù)制(MySQL Group Replication,MGR)
MGR有一些帥氣的能力:
(1)解決了單點寫入的問題,一個分組內(nèi)的所有節(jié)點都能夠?qū)懭?
(2)最終一致性,緩解了一致性問題,可以認(rèn)為大部分實例的數(shù)據(jù)都是最新的;
(3)高可用,系統(tǒng)故障時(即使是腦裂),系統(tǒng)依然可用;
如上圖所示:
(1)首先,分組內(nèi)的MySQL實例不再是“主從”關(guān)系,而是對等的“成員”關(guān)系,故每個節(jié)點都可以寫入;
(2)其次,增加了一個協(xié)商共識的認(rèn)證(certify)環(huán)節(jié),多數(shù)節(jié)點達(dá)成一致的事務(wù)才能提交;
畫外音:Garela也是此類機(jī)制。
和MySQL傳統(tǒng)的復(fù)制不同,MGR的核心是分布式共識算法,類似于Paxos。
基于上一篇《Galera,MySQL主從之外的另一種選擇》的留言,似乎大部分人都非常熟悉算法的底層內(nèi)核,本篇就先不展開了。
畫外音:感興趣的人多的話,再展開細(xì)講。
不知不覺寫了幾千字了,收個尾做個總結(jié)吧。
三類常見數(shù)據(jù)庫架構(gòu)
- Shared Everything:數(shù)據(jù)庫單機(jī)系統(tǒng),資源競爭;
- Shared Disk:Oracle Rac,計算與存儲分離;
- Shared Nothing:水平切分,復(fù)制集群,資源完全隔離;
三類常見復(fù)制方式
- 異步復(fù)制:傳統(tǒng)主從,互聯(lián)網(wǎng)公司最常用;
- 半同步復(fù)制:從庫確認(rèn),主庫才提交;
- 組復(fù)制:MySQL 5.7的新功能,核心在于分布式共識算法;
知其然,知其所以然。思路比結(jié)論更重要。
畫外音:對不起,讀完本文不止1分鐘。
【本文為51CTO專欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請聯(lián)系原作者】