朱哲哲,趙振海,李 鵬,吳海洋,向小佳
(光大科技有限公司,北京 100049)
數(shù)據(jù)庫(kù)的發(fā)展經(jīng)歷了從傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)、NoSQL (Not only SQL)[1]數(shù)據(jù)庫(kù)到近幾年新出現(xiàn)的分布式NewSQL 數(shù)據(jù)庫(kù),整個(gè)趨勢(shì)由單機(jī)逐漸向分布式方向發(fā)展.傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)的問(wèn)題在于,對(duì)可擴(kuò)展性以及高可用性的支持不足,單機(jī)數(shù)據(jù)庫(kù)容量有限,單表容量有限,無(wú)法支撐龐大的數(shù)據(jù)查詢處理需求.一種解決辦法是通過(guò)分庫(kù)分表將負(fù)載分散到多個(gè)表中,緩解數(shù)據(jù)庫(kù)壓力,或者增加磁盤(pán)和CPU 容量,但不能從根本上解決問(wèn)題.而NoSQL 數(shù)據(jù)庫(kù)雖然原生支持?jǐn)U展性和高可用性,數(shù)據(jù)模型更加靈活,但是對(duì)數(shù)據(jù)的強(qiáng)一致性卻無(wú)法保證,不支持原子事務(wù)(原子事務(wù)保證了跨多個(gè)節(jié)點(diǎn)事務(wù)操作的一致性,但是節(jié)點(diǎn)間協(xié)調(diào)會(huì)增加延時(shí),基于性能原因的考慮,當(dāng)前NoSQL實(shí)現(xiàn)的都是基于單一鍵的事務(wù)),而且NoSQL 不兼容傳統(tǒng)的SQL 語(yǔ)法,造成原有系統(tǒng)的遷移障礙.分布式NewSQL 數(shù)據(jù)庫(kù)的概念產(chǎn)生來(lái)源于Google 于2012年發(fā)表的Spanner[2]數(shù)據(jù)庫(kù),該論文將傳統(tǒng)關(guān)系模型以及NoSQL 數(shù)據(jù)庫(kù)的擴(kuò)展性相結(jié)合,使數(shù)據(jù)庫(kù)同時(shí)支持分布式又具有傳統(tǒng)SQL的能力.除了Spanner 數(shù)據(jù)庫(kù),國(guó)外的CockroachDB[3]以及國(guó)內(nèi)的TDSQL、MyCAT、TiDB[4]、OceanBase等都是新興的分布式數(shù)據(jù)庫(kù)產(chǎn)品.分布式數(shù)據(jù)庫(kù)從實(shí)現(xiàn)上可以分為兩類(lèi):一類(lèi)是在現(xiàn)有數(shù)據(jù)庫(kù)之上以中間件代理的形式,提供自動(dòng)分庫(kù)分表、故障切換、分布式事務(wù)等支持,以MyCAT、TDSQL 等為代表.一類(lèi)是原生的分布式架構(gòu),通過(guò)共識(shí)算法實(shí)現(xiàn)高可用性和數(shù)據(jù)一致性等支持,以TiDB、OceanBase 等為代表.
分布式數(shù)據(jù)庫(kù)常見(jiàn)的特點(diǎn)包括高可用、高可擴(kuò)展和數(shù)據(jù)強(qiáng)一致性等.對(duì)于可用性和數(shù)據(jù)一致性,根據(jù)分布式CAP[5]理論可知,在保證分區(qū)容錯(cuò)性的前提下,勢(shì)必要在數(shù)據(jù)一致性和可用性中做出權(quán)衡.其中可用性的保證可以通過(guò)復(fù)制實(shí)現(xiàn),通過(guò)在多臺(tái)機(jī)器上保存數(shù)據(jù)副本,提高系統(tǒng)可用性,MyCAT 以及TDSQL 均支持主從復(fù)制的方式.傳統(tǒng)主從復(fù)制方式的問(wèn)題在于雖然保證了可用性,但是數(shù)據(jù)的強(qiáng)一致性卻無(wú)法保證,如果主庫(kù)故障,可能會(huì)出現(xiàn)多個(gè)節(jié)點(diǎn)成為主庫(kù)(腦裂問(wèn)題[6]),導(dǎo)致數(shù)據(jù)丟失或損壞.MySQL 在5.7 版本推出了MySQL Group Replication 功能,實(shí)現(xiàn)了基于Paxos 共識(shí)算法[7]的可用性和數(shù)據(jù)一致性保證,TiDB 基于Raft 共識(shí)算法[8]保證了可用性和數(shù)據(jù)一致性.擴(kuò)展性的保證可通過(guò)分區(qū)的方式,將原有單個(gè)節(jié)點(diǎn)的壓力分散到多個(gè)節(jié)點(diǎn),提升系統(tǒng)性能.分區(qū)面臨的問(wèn)題是如何將數(shù)據(jù)和查詢負(fù)載均勻分布在各個(gè)節(jié)點(diǎn),常見(jiàn)的解決辦法有基于Hash 的分區(qū)和基于Range 的分區(qū),TiDB 使用Range的方式分區(qū),而OceanBase 兩種都支持.分布式數(shù)據(jù)庫(kù)的另一個(gè)特點(diǎn)是對(duì)事務(wù)的支持,分布式場(chǎng)景下保障事務(wù)的ACID 原則常見(jiàn)的辦法有2PC 協(xié)議、TCC 協(xié)議以及SAGA 協(xié)議,TiDB、OceanBase 等均使用2PC[9](兩階段提交協(xié)議)來(lái)實(shí)現(xiàn)跨多個(gè)節(jié)點(diǎn)的事務(wù)提交.除了對(duì)以上特點(diǎn)的支持,分布式數(shù)據(jù)庫(kù)還具有HTAP、SQL引擎、兼容性等特點(diǎn).
對(duì)金融行業(yè)來(lái)說(shuō),在數(shù)據(jù)庫(kù)系統(tǒng)可用性、數(shù)據(jù)一致性、交易延時(shí)等方面有更嚴(yán)格的要求,系統(tǒng)可用性要求99.99%以上,賬務(wù)交易對(duì)事務(wù)要求零容忍.本文基于國(guó)內(nèi)某銀行原有金融業(yè)務(wù)的分布式改造進(jìn)行研究,銀行原有數(shù)據(jù)庫(kù)架構(gòu)采用Oracle RAC 部署的方式,這種方式的問(wèn)題在于硬件成本高昂,無(wú)法有效橫向擴(kuò)展,隨著業(yè)務(wù)量的增大,系統(tǒng)性能以及存儲(chǔ)能力嚴(yán)重不足,故障切換時(shí)間長(zhǎng),更無(wú)法實(shí)現(xiàn)秒級(jí)切換,導(dǎo)致系統(tǒng)運(yùn)行風(fēng)險(xiǎn)增大.基于銀行業(yè)務(wù)對(duì)數(shù)據(jù)強(qiáng)一致性、高可用、橫向擴(kuò)展等要求,并結(jié)合銀行自身業(yè)務(wù)系統(tǒng)的特點(diǎn),本文在MySQL 集群作為數(shù)據(jù)節(jié)點(diǎn)的基礎(chǔ)上,利用自研的調(diào)度組件Grid,實(shí)現(xiàn)了具有高可用、動(dòng)態(tài)擴(kuò)展、分布式事務(wù)、HTAP 混合、兼容MySQL 等特性的分布式關(guān)系型數(shù)據(jù)庫(kù).該數(shù)據(jù)庫(kù)通過(guò)類(lèi)Raft 增強(qiáng)一致性算法和Zookeeper 自動(dòng)選主實(shí)現(xiàn)了整個(gè)系統(tǒng)組件的高可用,并通過(guò)Grid 組件調(diào)度,實(shí)現(xiàn)了自動(dòng)分庫(kù)分表、SQL 路由、分布式事務(wù)等功能的支持.
在架構(gòu)設(shè)計(jì)上,本文的分布式數(shù)據(jù)庫(kù)由調(diào)度節(jié)點(diǎn)、數(shù)據(jù)節(jié)點(diǎn)和配置節(jié)點(diǎn)構(gòu)成,如圖1所示.其中,數(shù)據(jù)節(jié)點(diǎn)基于MySQL 集群方案,負(fù)責(zé)數(shù)據(jù)存儲(chǔ)、本地事務(wù)管理、本地結(jié)果集計(jì)算等功能,Grid 調(diào)度節(jié)點(diǎn)負(fù)責(zé)全局事務(wù)管理、分布式執(zhí)行計(jì)劃的生成和調(diào)度、集群擴(kuò)縮容以及數(shù)據(jù)節(jié)點(diǎn)的高可用調(diào)度等功能,而配置節(jié)點(diǎn)基于Zookeeper[10]實(shí)現(xiàn),負(fù)責(zé)集群運(yùn)行態(tài)元數(shù)據(jù)的存儲(chǔ)同步以及配置管理.
圖1 分布式數(shù)據(jù)庫(kù)架構(gòu)
在數(shù)據(jù)節(jié)點(diǎn)的實(shí)現(xiàn)上,與TiDB 以及OceanBase 等分布式數(shù)據(jù)庫(kù)不同的是,本文使用了MySQL 集群的方案.MySQL5.7 版本之前,實(shí)現(xiàn)高可用一般的做法是主從復(fù)制的方式,常利用半同步保證節(jié)點(diǎn)間數(shù)據(jù)的一致,但仍無(wú)法滿足高可用的要求[11].本文采用了基于Raft實(shí)現(xiàn)的增強(qiáng)一致性算法(將在第3 節(jié)存儲(chǔ)中詳細(xì)闡述),通過(guò)增強(qiáng)Raft 算法的部分細(xì)節(jié)實(shí)現(xiàn),提供數(shù)據(jù)庫(kù)集群節(jié)點(diǎn)的強(qiáng)一致保證,解決了傳統(tǒng)主從復(fù)制容易出現(xiàn)的腦裂問(wèn)題.
調(diào)度節(jié)點(diǎn)Grid 主要用來(lái)進(jìn)行SQL 解析,實(shí)現(xiàn)分布式的SQL 語(yǔ)句執(zhí)行優(yōu)化.對(duì)于混合事務(wù)分析處理(HTAP)[12]的需求,除了原生支持分布式事務(wù)之外,對(duì)于在線分析處理需求,通過(guò)插件的形式提供Spark SQL 集成,將復(fù)雜語(yǔ)句通過(guò)SQL 引擎路由到Spark 端處理分析,而Spark 的數(shù)據(jù)則直接通過(guò)數(shù)據(jù)節(jié)點(diǎn)進(jìn)行抽取.對(duì)于分布式事務(wù)的實(shí)現(xiàn),采用了兩階段提交協(xié)議的標(biāo)準(zhǔn)實(shí)現(xiàn)——XA 事務(wù).本文的分布式數(shù)據(jù)庫(kù)中所有組件都是高可用和高擴(kuò)展的,以調(diào)度節(jié)點(diǎn)為例,在對(duì)外服務(wù)中利用F5提供負(fù)載均衡支持[13],組件本身基于配置節(jié)點(diǎn)實(shí)現(xiàn)分布式選主,實(shí)現(xiàn)多活高可靠.
配置節(jié)點(diǎn)層主要用來(lái)存儲(chǔ)調(diào)度層元數(shù)據(jù),提供調(diào)度節(jié)點(diǎn)的“領(lǐng)導(dǎo)選舉”.
除了上述提到的組件,本文也在數(shù)據(jù)庫(kù)安全上做了相應(yīng)支持,通過(guò)黑白名單檢查、登錄認(rèn)證和ACL 認(rèn)證等保護(hù)數(shù)據(jù)庫(kù)安全.
下面的章節(jié)本文將會(huì)對(duì)調(diào)度層SQL 引擎、事務(wù)和鎖的實(shí)現(xiàn)、存儲(chǔ)層實(shí)現(xiàn)和高可用等作更深入的闡述.
為了解決大規(guī)模數(shù)據(jù)量以及高負(fù)載下的數(shù)據(jù)分布問(wèn)題,本研究通過(guò)中間件的形式提供了對(duì)分庫(kù)分表、SQL引擎、事務(wù)與鎖等功能支持.調(diào)度層Grid 采用了XA兩階段事務(wù)以及對(duì)悲觀鎖和全隔離級(jí)別的支持.SQL引擎通過(guò)詞法分析對(duì)執(zhí)行語(yǔ)句進(jìn)行分布式改造,實(shí)現(xiàn)查詢下推和結(jié)果匯聚.
分布式場(chǎng)景下SQL 語(yǔ)句執(zhí)行[14]的一個(gè)要點(diǎn)是如何跨多個(gè)數(shù)據(jù)分片計(jì)算并收集結(jié)果,如何實(shí)現(xiàn)跨節(jié)點(diǎn)JOIN.解決方案在于通過(guò)某一種維度進(jìn)行切分操作,分步JOIN之后再將結(jié)果聚合.Grid 組件在SQL 引擎的實(shí)現(xiàn)上對(duì)語(yǔ)句進(jìn)行了并行改造,通過(guò)對(duì)語(yǔ)句添加后綴將其路由到不同的數(shù)據(jù)分片實(shí)現(xiàn)并行計(jì)算.執(zhí)行過(guò)程如圖2所示.
圖2 SQL 執(zhí)行過(guò)程
對(duì)于一個(gè)查詢語(yǔ)句來(lái)說(shuō),SQL 引擎首先對(duì)語(yǔ)句改造后生成查詢計(jì)劃,然后最大限度的將查詢下推,在多個(gè)節(jié)點(diǎn)進(jìn)行并行查詢計(jì)算,并進(jìn)行結(jié)果歸并.結(jié)果歸并的過(guò)程采用了流式歸并,其與數(shù)據(jù)庫(kù)原生的返回結(jié)果集的方式最為契合.流式歸并將每一次從結(jié)果集中取到的數(shù)據(jù),通過(guò)逐條獲取的方式得到正確的單條數(shù)據(jù).具體來(lái)說(shuō),一個(gè)查詢語(yǔ)句經(jīng)過(guò)SQL 引擎的步驟如下:
(1) 通過(guò)詞法語(yǔ)法解析獲取SQL 語(yǔ)句語(yǔ)義信息.
(2) 對(duì)SQL 語(yǔ)句進(jìn)行必要的分布式并行執(zhí)行改造.
(3) 盡可能地將查詢計(jì)算下推.
(4) 當(dāng)涉及到多個(gè)數(shù)據(jù)分片,查詢會(huì)并行下發(fā)到多個(gè)數(shù)據(jù)分片進(jìn)行并行計(jì)算.
(5) 根據(jù)執(zhí)行計(jì)劃對(duì)并行計(jì)算的結(jié)果集進(jìn)行歸并.
(6) 歸并過(guò)程盡可能采用流式歸并.
(7) 對(duì)于復(fù)雜的跨節(jié)點(diǎn)JOIN,通過(guò)分析語(yǔ)義將邏輯上獨(dú)立的子查詢塊拆分出來(lái)并行執(zhí)行.
對(duì)于上述步驟描述的并行執(zhí)行計(jì)算,Grid 在實(shí)現(xiàn)上采用了物理與邏輯結(jié)合的方式,通過(guò)物理表拆分與SQL 邏輯拆分相結(jié)合的數(shù)據(jù)分發(fā)及并行處理技術(shù),如圖3所示,實(shí)現(xiàn)在數(shù)據(jù)分布式部署和并行查詢執(zhí)行計(jì)劃兩個(gè)層面的性能優(yōu)化,相對(duì)于單數(shù)據(jù)庫(kù)實(shí)例,查詢效率提升N倍(N=邏輯拆分?jǐn)?shù)×虛擬分片數(shù)).
圖3 并行查詢
跨節(jié)點(diǎn)JOIN[15]作為分布式數(shù)據(jù)庫(kù)實(shí)現(xiàn)的難點(diǎn)之一,需要對(duì)普通表和分區(qū)表同時(shí)進(jìn)行支持,跨節(jié)點(diǎn)JOIN指的是多個(gè)節(jié)點(diǎn)的聯(lián)表查詢,比如“SELECT…FROM t1,t2 WHERE”查詢語(yǔ)句,涉及到兩張表以上的查詢.如何對(duì)多個(gè)節(jié)點(diǎn)數(shù)據(jù)多個(gè)表進(jìn)行JOIN,調(diào)度層Grid 采用的做法是通過(guò)引擎將復(fù)雜JOIN 拆分為多個(gè)子句,將子句劃分為表組(Table Group),生成執(zhí)行計(jì)劃,通過(guò)創(chuàng)建臨時(shí)表的方式進(jìn)行遷移[16],如圖4所示.以子句
圖4 跨節(jié)點(diǎn)JOIN
“SELECT … FROM tb1,tb2,tb3 WHERE”為例,首先會(huì)根據(jù)可以MERGE 的tb1和tb3 表生成一個(gè)表組,tb2為另一個(gè)表組,然后創(chuàng)建臨時(shí)表遷移.遷移的過(guò)程包含以下步驟:
(1) 在大表tb2 中創(chuàng)建記錄tb1,tb3 的臨時(shí)表.
(2) 生成tb1、tb3 的SELECT 計(jì)劃1 數(shù)據(jù)下推.
(3) 生成tb2 的SELECT 計(jì)劃2 同時(shí)創(chuàng)建臨時(shí)表.
(4) 執(zhí)行SELECT 計(jì)劃1 移動(dòng)到tb2 中的臨時(shí)表.
(5) 執(zhí)行SELECT 計(jì)劃2.
對(duì)于普通表和分區(qū)表的JOIN,會(huì)在分區(qū)表的每一個(gè)節(jié)點(diǎn)創(chuàng)建臨時(shí)表,然后將普通表遷移到分區(qū)表每個(gè)節(jié)點(diǎn)的臨時(shí)表中,對(duì)于有等值分區(qū)列的JOIN 條件,則會(huì)將普通表按照分區(qū)表的分區(qū)算法散列到不同節(jié)點(diǎn).如果子句中的表都是分區(qū)表,限制查詢WHERE 語(yǔ)句必須包含分區(qū)列,將表按照分區(qū)散列算法遷移到多個(gè)節(jié)點(diǎn).遷移完成后,在分區(qū)節(jié)點(diǎn)中并行計(jì)算JOIN 結(jié)果并返回.
對(duì)事務(wù)的支持是分布式數(shù)據(jù)庫(kù)和NoSQL 數(shù)據(jù)庫(kù)的一個(gè)主要區(qū)別,事務(wù)在數(shù)據(jù)庫(kù)中代表一系列操作要么全部完成,要么全部失敗[17],ACID 規(guī)定了事務(wù)操作的原子性、一致性、隔離性和持久性.在分布式情況下要保證ACID,常見(jiàn)的做法是使用兩階段提交算法(2PC).本文的分布式事務(wù)借鑒了XA 兩階段事務(wù)的實(shí)現(xiàn),通過(guò)事務(wù)管理器協(xié)調(diào)多節(jié)點(diǎn)之間的事務(wù),整個(gè)事務(wù)被分為準(zhǔn)備和提交兩個(gè)過(guò)程[18].
2PC 存在事務(wù)管理器故障導(dǎo)致數(shù)據(jù)庫(kù)節(jié)點(diǎn)無(wú)法獲知事務(wù)提交狀態(tài)的問(wèn)題.在事務(wù)提交時(shí),事務(wù)管理器崩潰或者網(wǎng)絡(luò)出現(xiàn)故障,而數(shù)據(jù)庫(kù)節(jié)點(diǎn)無(wú)法獲知當(dāng)前事務(wù)是否提交成功或者回滾,只能處于等待狀態(tài).常見(jiàn)做法是將事務(wù)提交或者終止的狀態(tài)寫(xiě)入日志,在事務(wù)管理器恢復(fù)后,可以通過(guò)日志信息繼續(xù)事務(wù)過(guò)程.Grid 在實(shí)現(xiàn)上將分布式事務(wù)日志存儲(chǔ)在數(shù)據(jù)節(jié)點(diǎn)的元數(shù)據(jù)表中,同時(shí)提供主備數(shù)據(jù)副本支持.事務(wù)日志在數(shù)據(jù)節(jié)點(diǎn)中使用類(lèi)Raft 增強(qiáng)一致性同步協(xié)議確保數(shù)據(jù)強(qiáng)一致(類(lèi)Raft 協(xié)議的實(shí)現(xiàn)將在存儲(chǔ)一節(jié)詳細(xì)介紹),事務(wù)日志中包含了關(guān)聯(lián)節(jié)點(diǎn)的信息和提交狀態(tài),在出現(xiàn)故障時(shí),通過(guò)關(guān)聯(lián)事務(wù)日志列表和狀態(tài)日志匯總結(jié)果計(jì)算出事務(wù)提交列表以及回滾列表,將結(jié)果應(yīng)用到對(duì)應(yīng)的節(jié)點(diǎn)上.
在鎖的支持上,Grid 實(shí)現(xiàn)了與MySQL 一致的支持,LOCK TABLE 會(huì)導(dǎo)致隱式提交,而DDL 語(yǔ)句導(dǎo)致事務(wù)的隱式提交,同時(shí)支持顯式行鎖以及FLUSH TABLE全局鎖.
分布式數(shù)據(jù)庫(kù)存儲(chǔ)層常見(jiàn)的方案有使用關(guān)系型數(shù)據(jù)庫(kù)(MySQL 等)和非關(guān)系型的鍵值數(shù)據(jù)庫(kù),比如TiDB和CockroachDB 都使用鍵值數(shù)據(jù)庫(kù)RocksDB[19]作為其存儲(chǔ)層實(shí)現(xiàn).鍵值數(shù)據(jù)庫(kù)常見(jiàn)的底層存儲(chǔ)模型包括LSM-Tree[20]、B-Tree和Hash 模型,LevelDB 及其變種RocksDB 皆使用LSM-Tree 模型,內(nèi)存型數(shù)據(jù)庫(kù)Redis 使用的是Hash 模型,對(duì)于關(guān)系型數(shù)據(jù)庫(kù)來(lái)說(shuō),其底層存儲(chǔ)模型常使用B 樹(shù)或者其變種,比如MySQL使用的就是B+樹(shù).本文在底層數(shù)據(jù)庫(kù)中使用MySQL數(shù)據(jù)庫(kù)作為數(shù)據(jù)集群,這樣可以最大限度的兼容原有MySQL 數(shù)據(jù)庫(kù),而以TiDB 等為代表的數(shù)據(jù)庫(kù)需要在存儲(chǔ)層和MySQL 的兼容性方面提供轉(zhuǎn)換層,對(duì)SQL語(yǔ)法的兼容性也不夠好.在集群的實(shí)現(xiàn)上,原生MySQL主從復(fù)制實(shí)現(xiàn)的可用性方案有諸多問(wèn)題,如果為同步復(fù)制,存在從節(jié)點(diǎn)失去響應(yīng)后導(dǎo)致主節(jié)點(diǎn)無(wú)法處理寫(xiě)入操作的問(wèn)題.另外主節(jié)點(diǎn)故障后如何選擇新的領(lǐng)導(dǎo)者(共識(shí)問(wèn)題),還可能出現(xiàn)腦裂的現(xiàn)象.本文使用類(lèi)Raft 的增強(qiáng)算法來(lái)保證數(shù)據(jù)的強(qiáng)一致性.
Raft 作為經(jīng)典的共識(shí)算法,在2014 由Ongaro 根據(jù)Paxos 算法簡(jiǎn)化而來(lái)[8],Raft 通過(guò)領(lǐng)導(dǎo)選舉機(jī)制、日志復(fù)寫(xiě)和安全性機(jī)制保證集群節(jié)點(diǎn)在狀態(tài)轉(zhuǎn)換間的一致.除了對(duì)原有的算法實(shí)現(xiàn)外,本文在具體的算法細(xì)節(jié)上也做了相應(yīng)增強(qiáng),在實(shí)現(xiàn)上與Raft 算法中元素的對(duì)應(yīng)關(guān)系如表1所示.
表1 Raft 算法對(duì)應(yīng)實(shí)現(xiàn)
在領(lǐng)導(dǎo)選舉的實(shí)現(xiàn)上,通過(guò)數(shù)據(jù)副本的復(fù)制指向關(guān)系進(jìn)行投票,領(lǐng)導(dǎo)者在任期內(nèi)的Term 通過(guò)master_version 進(jìn)行維護(hù),如果主節(jié)點(diǎn)發(fā)生故障,調(diào)度節(jié)點(diǎn)Grid會(huì)通過(guò)RequestVote RPC 進(jìn)行冗余節(jié)點(diǎn)探測(cè)來(lái)觸發(fā)新投票過(guò)程,在投票過(guò)半數(shù)的情況下,首先遍歷所有存活候選從節(jié)點(diǎn),選取master_version 最大的節(jié)點(diǎn),并且檢查候選節(jié)點(diǎn)是否有巨大的復(fù)制延遲,首先選擇從節(jié)點(diǎn)版本最新的節(jié)點(diǎn)作為主節(jié)點(diǎn),如果無(wú)可用節(jié)點(diǎn)的話,則從延遲過(guò)大的節(jié)點(diǎn)中選擇.Raft 中主節(jié)點(diǎn)使用Append-Entries RPC 來(lái)向從節(jié)點(diǎn)同步日志和檢測(cè)從節(jié)點(diǎn)狀態(tài),本文的AppendEntries RPC 實(shí)現(xiàn)基于半同步復(fù)制,從節(jié)點(diǎn)直接對(duì)日志進(jìn)行應(yīng)用,同時(shí)基于閃回處理故障恢復(fù)節(jié)點(diǎn)[21,22].具體過(guò)程如圖5所示.
圖5 類(lèi)Raft 增強(qiáng)一致性算法
在分布式數(shù)據(jù)庫(kù)的設(shè)計(jì)上,本文通過(guò)全組件的冗余設(shè)計(jì),保障了數(shù)據(jù)庫(kù)系統(tǒng)的高可用.在調(diào)度節(jié)點(diǎn)通過(guò)LVS 或F5 對(duì)外提供服務(wù),而調(diào)度節(jié)點(diǎn)本身基于配置節(jié)點(diǎn)進(jìn)行分布式領(lǐng)導(dǎo)選舉,保證節(jié)點(diǎn)可用性.數(shù)據(jù)節(jié)點(diǎn)的高可用保證通過(guò)采用類(lèi)Raft 增強(qiáng)一致性同步協(xié)議實(shí)現(xiàn).配置節(jié)點(diǎn)基于Zookeeper 實(shí)現(xiàn)了原生高可靠的支持,支持雙機(jī)房切換恢復(fù).
調(diào)度節(jié)點(diǎn)作為分布式數(shù)據(jù)庫(kù)的核心,依賴配置節(jié)點(diǎn)存儲(chǔ)調(diào)度信息.調(diào)度節(jié)點(diǎn)為主從模式,其關(guān)鍵在于主節(jié)點(diǎn)故障時(shí)如何在從節(jié)點(diǎn)中選取新的領(lǐng)導(dǎo)者,同時(shí)由于調(diào)度節(jié)點(diǎn)相對(duì)于數(shù)據(jù)節(jié)點(diǎn)不涉及業(yè)務(wù)數(shù)據(jù),只有少量元數(shù)據(jù)需要同步,因此調(diào)度節(jié)點(diǎn)Grid 直接使用Zookeeper中的Zab 算法[23]來(lái)保證.調(diào)度節(jié)點(diǎn)之上基于F5,從硬件層面保證負(fù)載均衡實(shí)現(xiàn)多活高可靠.如圖6所示.
圖6 高可用
數(shù)據(jù)節(jié)點(diǎn)的高可用通過(guò)MySQL 數(shù)據(jù)庫(kù)集群,使用類(lèi)Raft 增強(qiáng)一致性算法實(shí)現(xiàn)單節(jié)點(diǎn)宕機(jī)后其他節(jié)點(diǎn)也能正常提供服務(wù),保障高可用,同時(shí)也保證了節(jié)點(diǎn)間數(shù)據(jù)的一致,具體實(shí)現(xiàn)細(xì)節(jié)在存儲(chǔ)一節(jié)有介紹.
除了高可用外,在擴(kuò)展性方面,系統(tǒng)中的所有節(jié)點(diǎn)均可動(dòng)態(tài)添加和刪除,不影響系統(tǒng)運(yùn)行.其中,調(diào)度節(jié)點(diǎn)依賴Zookeeper 同時(shí)實(shí)現(xiàn)了集群節(jié)點(diǎn)的動(dòng)態(tài)增減,保證了整個(gè)集群吞吐性能的橫向擴(kuò)展,通過(guò)從節(jié)點(diǎn)的在線添加與在線刪除實(shí)現(xiàn)節(jié)點(diǎn)在線滾動(dòng)升級(jí).而數(shù)據(jù)節(jié)點(diǎn)的擴(kuò)展,同時(shí)支持邏輯和物理上的在線單調(diào)重分布.
為了更直觀的了解本文分布式數(shù)據(jù)庫(kù)的性能,實(shí)驗(yàn)采用標(biāo)準(zhǔn)的TPC-C 數(shù)據(jù)庫(kù)基準(zhǔn),使用國(guó)產(chǎn)鯤鵬服務(wù)器集群對(duì)分布式事務(wù)性能(TPMC)進(jìn)行測(cè)試.其中,每臺(tái)鯤鵬服務(wù)器配置為泰山服務(wù)器2280 v2、兩個(gè)KunPeng920 64 核CPU、內(nèi)存64 GB、系統(tǒng)盤(pán)和數(shù)據(jù)盤(pán)分別為兩個(gè)600 GB SAS 盤(pán)、12 個(gè)800 GB SAS SSD.實(shí)驗(yàn)通過(guò)控制集群節(jié)點(diǎn)數(shù)的增加,測(cè)試數(shù)據(jù)庫(kù)在事務(wù)處理上的性能,測(cè)試結(jié)果如圖7所示.
圖7 TPMC 1000 倉(cāng)庫(kù)
從圖7可以看出,本文的分布式數(shù)據(jù)庫(kù)在3 節(jié)點(diǎn)的集群上每分鐘最高可以達(dá)到110 w 的事務(wù)處理,隨著節(jié)點(diǎn)的數(shù)的增加,事務(wù)處理能力也線性上升,在6 節(jié)點(diǎn)集群中事務(wù)處理可以達(dá)到每分鐘220 w,橫向擴(kuò)展比大于0.95.證明了該數(shù)據(jù)庫(kù)在性能上以及擴(kuò)展上的優(yōu)秀表現(xiàn).
目前,分布式數(shù)據(jù)庫(kù)已經(jīng)在國(guó)內(nèi)某銀行業(yè)務(wù)系統(tǒng)中使用,經(jīng)過(guò)技術(shù)方案、前期業(yè)務(wù)功能試點(diǎn),該系統(tǒng)全部繳費(fèi)業(yè)務(wù)單元已經(jīng)逐步遷移到分布式數(shù)據(jù)庫(kù)系統(tǒng)中.
原有數(shù)據(jù)庫(kù)經(jīng)過(guò)分布式改造之后,在架構(gòu)上更加清晰,分布式數(shù)據(jù)庫(kù)對(duì)外仍然像單機(jī)數(shù)據(jù)庫(kù)一樣提供服務(wù).在系統(tǒng)部署架構(gòu)上,采用雙機(jī)房運(yùn)行的方式,利用兩臺(tái)備份服務(wù)器和兩臺(tái)逃生服務(wù)器保障數(shù)據(jù)完整,在數(shù)據(jù)節(jié)點(diǎn)的配置上,MySQL 集群節(jié)點(diǎn)采用一主一從和兩從節(jié)點(diǎn)分機(jī)房運(yùn)行的方式,通過(guò)配置保障同機(jī)房和跨機(jī)房數(shù)據(jù)強(qiáng)一致性,調(diào)度節(jié)點(diǎn)各機(jī)房使用三臺(tái)服務(wù)器為系統(tǒng)提供調(diào)度保障.
經(jīng)過(guò)對(duì)分布式數(shù)據(jù)庫(kù)實(shí)際運(yùn)行中的測(cè)試,銀行業(yè)務(wù)系統(tǒng)在聯(lián)機(jī)同步交易單筆查詢和繳費(fèi)響應(yīng)的時(shí)間小于100 ms,在可用性方面,系統(tǒng)整體可用率達(dá)到99.99%,并且數(shù)據(jù)不易丟失和損壞.相較于原有數(shù)據(jù)庫(kù)系統(tǒng),現(xiàn)有分布式數(shù)據(jù)庫(kù)有更靈活的擴(kuò)展能力,集群可動(dòng)態(tài)擴(kuò)展,各個(gè)功能節(jié)點(diǎn)發(fā)生故障可實(shí)時(shí)切換,系統(tǒng)發(fā)生故障的次數(shù)也大幅度下降.
本文研究并實(shí)現(xiàn)了基于Raft 的增強(qiáng)一致性算法和Zookeeper 集群調(diào)度的分布式數(shù)據(jù)庫(kù)系統(tǒng),通過(guò)全節(jié)點(diǎn)的冗余設(shè)計(jì)以及調(diào)度層對(duì)SQL 引擎和分布式事務(wù)的研究實(shí)現(xiàn),為大規(guī)模金融數(shù)據(jù)的高可用以及強(qiáng)一致性提供了有力支持.在數(shù)據(jù)庫(kù)測(cè)試中表現(xiàn)出了優(yōu)異的性能,在實(shí)際金融業(yè)務(wù)系統(tǒng)的穩(wěn)定運(yùn)行也表明該系統(tǒng)在金融行業(yè)應(yīng)用的優(yōu)勢(shì).不過(guò),本文的分布式數(shù)據(jù)庫(kù)在設(shè)計(jì)與實(shí)現(xiàn)上也有不足之處,比如限于研發(fā)難度使用多種一致性算法,增加了運(yùn)維難度,后續(xù)會(huì)在這方面進(jìn)一步改進(jìn).