MySQL架構(gòu)演進(jìn)-從主從復(fù)制到分庫(kù)分表
發(fā)布日期:2022/9/19 10:20:39 瀏覽量:
背景
業(yè)務(wù)飛速發(fā)展導(dǎo)致數(shù)據(jù)規(guī)模急速膨脹,單機(jī)的數(shù)據(jù)庫(kù)已經(jīng)無(wú)法滿足互聯(lián)網(wǎng)業(yè)務(wù)的發(fā)展。 傳統(tǒng)的將數(shù)據(jù)集中存儲(chǔ)單一數(shù)據(jù)結(jié)節(jié)的方案,在容量、性能、可用性和可維護(hù)性方面已經(jīng)難以滿足互聯(lián)網(wǎng)海量數(shù)據(jù)的場(chǎng)景。 從容量方面考慮,單機(jī)數(shù)據(jù)庫(kù)容量有限,難以擴(kuò)容。 從性能方面來(lái)說(shuō),由于關(guān)系型數(shù)據(jù)庫(kù)大多數(shù)采用B+樹類型索引,在數(shù)據(jù)量超過(guò)一定的閾值后,索引的深度增加導(dǎo)致對(duì)磁盤的隨機(jī)IO次數(shù)增加,進(jìn)而導(dǎo)致性能問(wèn)題。 從可用性方面來(lái)說(shuō),服務(wù)通常設(shè)計(jì)成無(wú)狀態(tài)的,這必然導(dǎo)致系統(tǒng)的存儲(chǔ)壓力都集中在數(shù)據(jù)庫(kù)層面,而單一的數(shù)據(jù)節(jié)點(diǎn),或者簡(jiǎn)單的主從架構(gòu),已經(jīng)越來(lái)越難以承擔(dān)。 從運(yùn)維角度來(lái)看,當(dāng)數(shù)據(jù)都集中在一個(gè)節(jié)點(diǎn)上時(shí),數(shù)據(jù)備份和恢復(fù)的時(shí)間成本也隨之?dāng)?shù)據(jù)量上升變得不可控。同時(shí)數(shù)據(jù)丟失導(dǎo)致影響的范圍也會(huì)被放大。
主從復(fù)制
主庫(kù)將事務(wù)操作(除了查詢以外的操作)記錄到binlog
從庫(kù)通過(guò)relay log同步數(shù)據(jù),實(shí)現(xiàn)數(shù)據(jù)的同步
binlog日志格式
row 記錄數(shù)據(jù)庫(kù)操作詳細(xì)記錄,包括上線文信息等,文件較大。
statement 記錄事務(wù)相關(guān)的SQL文件。
mixed 混合式, 基于row和statement兩種文件格式。
異步復(fù)制
2000年,MySQL3.23.15版本引入復(fù)制功能,采用異步復(fù)制的方式,當(dāng)網(wǎng)絡(luò)或者機(jī)器故障,會(huì)導(dǎo)致數(shù)據(jù)不一致。
半同步復(fù)制
2010年, MySQL 5.5版本引入半同步復(fù)制, 半同步復(fù)制是指只要一個(gè)salve節(jié)點(diǎn)返回ack,master節(jié)點(diǎn)就可以提交事務(wù)了,保證數(shù)據(jù)庫(kù)至少有一個(gè)節(jié)點(diǎn)完成了數(shù)據(jù)的同步。
組復(fù)制
2016年,MysQL在5.7.17中引入InnoDB Group Replication,該方案基于paxos協(xié)議實(shí)現(xiàn)組內(nèi)復(fù)制,保證數(shù)據(jù)一致性,paxos協(xié)議核心在于過(guò)半選舉。
主從復(fù)制的問(wèn)題
主從復(fù)制延遲,導(dǎo)致"寫完讀"數(shù)據(jù)不一致問(wèn)題。
從庫(kù)讀取失敗,再去主庫(kù)執(zhí)行一遍SQL,存在性能問(wèn)題。
業(yè)務(wù)層保證系統(tǒng)核心功能可用,將核心功能的CRUD操作都路由到主庫(kù),非核心業(yè)務(wù)功能即使存在短暫數(shù)據(jù)不一致也影響不大。
路由問(wèn)題,需要業(yè)務(wù)層根據(jù)SQL路由到不同的數(shù)據(jù)庫(kù),路由到SLAVE節(jié)點(diǎn)時(shí),還需要保證系統(tǒng)負(fù)載均衡。
業(yè)務(wù)層通過(guò)框架(如sharding-jdbc)或者手動(dòng)實(shí)現(xiàn),對(duì)業(yè)務(wù)的侵入性較大,已存在的舊系統(tǒng)改造不友好。
通過(guò)數(shù)據(jù)庫(kù)中間件實(shí)現(xiàn)(如mycat、sharding-proxy),需要部署一個(gè)中間件(中間件實(shí)現(xiàn)SQL標(biāo)準(zhǔn)),規(guī)則配置在中間件,執(zhí)行過(guò)程中會(huì)多一次網(wǎng)絡(luò)轉(zhuǎn)發(fā)。
不能保證系統(tǒng)高可用
通過(guò)一系列高可用的解決方案保證數(shù)據(jù)庫(kù)高可用
數(shù)據(jù)庫(kù)高可用
什么是高可用?
高可用意味著,更少的服務(wù)不可用的時(shí)間,一般用SLA(服務(wù)級(jí)別協(xié)議)衡量。
1年 = 365天 = 8760小時(shí)
99 = 8760 * 1% = 8760 * 0.01 = 87.6小時(shí)
99.9 = 8760 * 0.1% = 8760 * 0.001 = 8.76小時(shí)
99.99 = 8760 * 0.0001 = 0.876小時(shí) = 0.876 * 60 = 52.6分鐘
99.999 = 8760 * 0.00001 = 0.0876小時(shí) = 0.0876 * 60 = 5.26分鐘
為什么要做高可用?
通過(guò)故障轉(zhuǎn)移,提供failover的能力,加上業(yè)務(wù)側(cè)連接池的心跳重試,實(shí)現(xiàn)斷線重連,業(yè)務(wù)不間斷,降低RTO(Recovery Time Objective,復(fù)原時(shí)間目標(biāo))和RPO(Recovery Point Objective,復(fù)原點(diǎn)目標(biāo))。
容災(zāi)恢復(fù):冷備和熱備,冷備和熱備的區(qū)別在于運(yùn)行期間是否提供服務(wù)。
對(duì)于主從來(lái)說(shuō),簡(jiǎn)單的來(lái)說(shuō)就是Master節(jié)點(diǎn)掛了,某一個(gè)從節(jié)點(diǎn),自動(dòng)切換成主。
從集群來(lái)看,即便是個(gè)別節(jié)點(diǎn)掛了,能正常對(duì)外提供服務(wù)。
常見的策略:
多實(shí)例部署
跨機(jī)房部署
兩地三中心容災(zāi)高可用方案等。
手動(dòng)切換
即如果主節(jié)點(diǎn)宕機(jī),手動(dòng)將某個(gè)從節(jié)點(diǎn)修改成主節(jié)點(diǎn)。
存在的問(wèn)題:
可能數(shù)據(jù)不一致
需要人工干預(yù)
代碼和配置的侵入性,需要配置其他節(jié)點(diǎn),修改應(yīng)用數(shù)據(jù)源的配置。
MHA
MHA全稱叫做MySQL Master High Availability,是由Facebook工程師Yoshinori Matsunobu開發(fā)的一款MySQL高可用框架,基于Perl語(yǔ)言開發(fā),一般能在30秒內(nèi)實(shí)現(xiàn)主從切換,切換時(shí)通過(guò)SSH復(fù)制主節(jié)點(diǎn)的日志信息。
MHA負(fù)責(zé)MySQL主庫(kù)的高可用,當(dāng)主庫(kù)發(fā)生故障時(shí),MHA會(huì)選擇一個(gè)數(shù)量最接近原主庫(kù)的候選節(jié)點(diǎn)作為新的主節(jié)點(diǎn),并且補(bǔ)齊和之前宕機(jī)的Master差異的Binlog。數(shù)據(jù)補(bǔ)齊后,即將寫VIP漂移到新的主庫(kù)上。具體的架構(gòu)圖如下:
優(yōu)點(diǎn)
可以進(jìn)行根據(jù)具體的故障實(shí)現(xiàn)自動(dòng)檢測(cè)和故障轉(zhuǎn)移
擴(kuò)展性好,可以任意的擴(kuò)展數(shù)據(jù)節(jié)點(diǎn)數(shù)量
缺點(diǎn):
極限情況下,可能會(huì)發(fā)生腦裂現(xiàn)象,出現(xiàn)多個(gè)Master。
需要配置SSH信息。
至少需要三臺(tái)。
MGR
MGR是數(shù)據(jù)庫(kù)支持的,只需要配置插件即可,如果主節(jié)點(diǎn)掛掉,將自動(dòng)選擇某個(gè)從改為主。無(wú)需人工干預(yù),并且基于組復(fù)制(paxos算法),保證數(shù)據(jù)一致性。
MGR的特點(diǎn)
高一致性,基于分布式Paxos協(xié)議實(shí)現(xiàn)復(fù)制,保證數(shù)據(jù)一致性。
高容錯(cuò)性,自動(dòng)檢測(cè)機(jī)制,只要大多數(shù)節(jié)點(diǎn)都宕機(jī)的情況下,數(shù)據(jù)庫(kù)可以繼續(xù)工作,內(nèi)置防腦裂保護(hù)機(jī)制。
高可擴(kuò)展性,加入新節(jié)點(diǎn)后,自動(dòng)實(shí)現(xiàn)增量同步,直到與其他節(jié)點(diǎn)數(shù)據(jù)一致。
高靈活性,提供了單主和多主模式,單主模式支持主節(jié)點(diǎn)宕機(jī),自動(dòng)選主,多主模式支持多節(jié)點(diǎn)寫入。
MySQL InnoDb Cluster,一個(gè)完整的數(shù)據(jù)庫(kù)高可用解決框架,由多個(gè)組件組成
MySQL Group Replication,提供DB的擴(kuò)展,故障遷移
MySQL Router,輕量級(jí)中間件,提供應(yīng)用程序連接目標(biāo)的故障轉(zhuǎn)移。
MySQL shell,新的MySQL客戶端,多種接口模式,可以設(shè)置群組復(fù)制和Router。
Orchestrator
一款MySQL高可用和復(fù)制拓?fù)涔芾砉ぞ?,支持?fù)制拓?fù)浣Y(jié)構(gòu)的調(diào)整,自動(dòng)故障遷移和手動(dòng)切換的功能等,直接拖拽UI,就可以實(shí)現(xiàn)主從切換。
分庫(kù)分表
分庫(kù)分表通常是指垂直分庫(kù)和水平分表,對(duì)于垂直分表其實(shí)就是將寬表拆分成小表,沒(méi)有太多的技術(shù)挑戰(zhàn),這里側(cè)重講講垂直分庫(kù)和水平分表。
垂直分庫(kù)
垂直分庫(kù)是指將數(shù)據(jù)庫(kù)進(jìn)行縱向切分,通常按照業(yè)務(wù)的維度進(jìn)行劃分。
如典型的微服務(wù)的架構(gòu),將系統(tǒng)按照業(yè)務(wù)維度垂直拆分,劃分成多個(gè)服務(wù)。如一個(gè)電商網(wǎng)站可以拆分成:訂單、商品、會(huì)員、支付等服務(wù)。
垂直分庫(kù)后業(yè)務(wù)更加單純,職責(zé)單一,同時(shí)可以解決部分?jǐn)?shù)據(jù)庫(kù)容量問(wèn)題,但是同時(shí)也引入了新的技術(shù)復(fù)雜度,如下:
分布式事務(wù),跨數(shù)據(jù)庫(kù)的事務(wù)操作需要分布式事務(wù)支持,否則系統(tǒng)將會(huì)面臨數(shù)據(jù)不一致的問(wèn)題。
方案一,采用XA事務(wù),XA事務(wù)是數(shù)據(jù)庫(kù)本身支持規(guī)范,具備強(qiáng)一致性的特征,但是性能比較差,對(duì)于追求高性能的場(chǎng)景不適合使用XA事務(wù)。
方案二,采用柔性事務(wù),柔性事務(wù)是指,數(shù)據(jù)庫(kù)保證局部事務(wù),全局事務(wù)實(shí)現(xiàn)由業(yè)務(wù)層實(shí)現(xiàn)(如通過(guò)調(diào)度補(bǔ)償,重試補(bǔ)償,人工介入等),柔性事務(wù)常見的解決方案有:TCC、利用消息隊(duì)列實(shí)現(xiàn)事務(wù)。
join問(wèn)題,分庫(kù)后,表分散到不同的數(shù)據(jù)庫(kù),無(wú)法直接使用SQL進(jìn)行JOIN操作,需要業(yè)務(wù)層自己實(shí)現(xiàn)聚合操作,增加了開發(fā)成本。
水平分表
水平分表是指,將表按照某種規(guī)則分成多張表,拆分后的表結(jié)構(gòu)和拆分前完全一致,但是數(shù)據(jù)分散到多張表中,也可以成為數(shù)據(jù)分片。
通過(guò)水平分表,解決了單表的容量和性能問(wèn)題。但同時(shí),水平分表后,引入了新的技術(shù)復(fù)雜度,主要有以下幾點(diǎn):
路由問(wèn)題,當(dāng)業(yè)務(wù)層通過(guò)SQL對(duì)數(shù)據(jù)庫(kù)進(jìn)行DML操作時(shí),到底該查詢那張表呢?
方案一:范圍路由。根據(jù)表中某一列(分片鍵)的取值范圍進(jìn)行分表,如根據(jù)創(chuàng)建時(shí)間將主表分成多張表,每個(gè)月的數(shù)據(jù)單獨(dú)存儲(chǔ)在一個(gè)表中。范圍路由可能出現(xiàn)數(shù)據(jù)分配不均勻的現(xiàn)象,但是表數(shù)量易于擴(kuò)展。
方案二:哈希路由。根據(jù)表中某一列與分片數(shù)量取模運(yùn)算(field_value % table_num)。hash路由和范圍路由相反。表數(shù)量擴(kuò)展時(shí)都會(huì)導(dǎo)致數(shù)據(jù)重新分布,但是數(shù)據(jù)分布較為均勻。
join問(wèn)題,由于分表后,數(shù)據(jù)分散到多個(gè)表中,JOIN的條件語(yǔ)句中如果沒(méi)有分片鍵,那么需要將全部的分片表都JOIN一遍,這種操作會(huì)存在性能問(wèn)題。
count問(wèn)題,分表后,如果需要統(tǒng)計(jì)表記錄總和,需要遍歷所有的表,然后再將結(jié)果進(jìn)行匯總,可以通過(guò)一張單獨(dú)的匯總表來(lái)解決,但這種解決方案需要每次insert或者delete的時(shí)候就需要更新匯總表,如果有一次沒(méi)有更新,就會(huì)導(dǎo)致數(shù)據(jù)不一致。
order by問(wèn)題,分表后,如果需要進(jìn)行排序,需要遍歷所有的表,然后在代碼層進(jìn)行重新排序,這個(gè)操作一看就會(huì)存在性能問(wèn)題。
分庫(kù)分表解決方案
業(yè)務(wù)代碼層解決,可以通過(guò)SQL手動(dòng)處理路由,但是和業(yè)務(wù)的耦合很嚴(yán)重,不易于維護(hù)。通常采用集成jar包的方式進(jìn)行解決,如集成成熟的開源項(xiàng)目:sharding-jdbc。
數(shù)據(jù)庫(kù)中間件,數(shù)據(jù)庫(kù)中間件實(shí)現(xiàn)了對(duì)應(yīng)數(shù)據(jù)庫(kù)的SQL標(biāo)準(zhǔn),路由規(guī)則配置在數(shù)據(jù)庫(kù)中間件,業(yè)務(wù)代碼操作數(shù)據(jù)庫(kù)中間件和直接操作數(shù)據(jù)庫(kù)沒(méi)有任何區(qū)別。
總結(jié)
從單節(jié)點(diǎn)數(shù)據(jù)庫(kù)到主從復(fù)制,再到數(shù)據(jù)庫(kù)高可用,再到分庫(kù)分表,很好的解決了數(shù)據(jù)的性能、容量、高可用、運(yùn)維性等問(wèn)題,但是會(huì)帶來(lái)分布式事務(wù)、復(fù)雜SQL難以操作、SQL路由等問(wèn)題。
架構(gòu)設(shè)計(jì)應(yīng)該遵循:"簡(jiǎn)單性"、"合適性"、"演化性"的原則,符合當(dāng)前的業(yè)務(wù)發(fā)展,所以系統(tǒng)設(shè)計(jì)沒(méi)有必要一上來(lái)就考慮分庫(kù)分表,而應(yīng)該是數(shù)據(jù)量達(dá)到一定的量,出現(xiàn)性能瓶頸的時(shí)候再對(duì)系統(tǒng)進(jìn)行改造和優(yōu)化。
馬上咨詢: 如果您有業(yè)務(wù)方面的問(wèn)題或者需求,歡迎您咨詢!我們帶來(lái)的不僅僅是技術(shù),還有行業(yè)經(jīng)驗(yàn)積累。
QQ: 39764417/308460098 Phone: 13 9800 1 9844 / 135 6887 9550 聯(lián)系人:石先生/雷先生