新聞中心
PolarDB-X前身是淘寶內(nèi)部使用的分庫(kù)分表中間件TDDL(2007年,Java庫(kù)的形態(tài)),早期以DRDS(2012年開(kāi)始研發(fā),2014年上線,分庫(kù)分表中間件+MySQL Proxy的形態(tài))的品牌在阿里云上提供服務(wù),后來(lái)(2019年)正式轉(zhuǎn)型為分布式數(shù)據(jù)庫(kù)PolarDB-X(正式成為了PolarDB品牌的一員)。從中間件到分布式數(shù)據(jù)庫(kù),我們?cè)谝訫ySQL為存儲(chǔ)構(gòu)建分布式數(shù)據(jù)庫(kù)這條路上走了10余年,這中間積累了大量的技術(shù),也走了一些彎路,未來(lái)我們也會(huì)堅(jiān)定的走下去。

成都創(chuàng)新互聯(lián)公司基于成都重慶香港及美國(guó)等地區(qū)分布式IDC機(jī)房數(shù)據(jù)中心構(gòu)建的電信大帶寬,聯(lián)通大帶寬,移動(dòng)大帶寬,多線BGP大帶寬租用,是為眾多客戶提供專業(yè)綿陽(yáng)服務(wù)器托管報(bào)價(jià),主機(jī)托管價(jià)格性價(jià)比高,為金融證券行業(yè)服務(wù)器托管,ai人工智能服務(wù)器托管提供bgp線路100M獨(dú)享,G口帶寬及機(jī)柜租用的專業(yè)成都idc公司。
PolarDB-X的發(fā)展過(guò)程主要分成了中間件(DRDS)和數(shù)據(jù)庫(kù)(PolarDB-X)兩個(gè)階段,這兩個(gè)階段存在著巨大的差異。筆者參與PolarDB-X的開(kāi)發(fā)恰好剛滿十年,全程經(jīng)歷了整個(gè)發(fā)展過(guò)程。今天就和大家嘮一嘮PolarDB-X發(fā)展與轉(zhuǎn)型過(guò)程中的一些有意思的事情。
中間件時(shí)代(2012~2019)
DRDS時(shí)期的發(fā)展思路其實(shí)很簡(jiǎn)單,滿足用戶的幾個(gè)主要訴求:
阿里云上提供的RDS MySQL單實(shí)例最大存儲(chǔ)空間有限制(例如早期只有2T);
Share Storage的數(shù)據(jù)庫(kù)可以解決磁盤容量問(wèn)題,但依然受到單機(jī)CPU\內(nèi)存的限制,無(wú)法解決寫擴(kuò)展性的問(wèn)題;
使用開(kāi)源中間件能解決上述問(wèn)題,但做擴(kuò)容等運(yùn)維操作十分的麻煩復(fù)雜。
在這樣的背景下,我們?cè)谥虚g件TDDL之上增加了一個(gè)MySQL Proxy(實(shí)際上是Cobar的網(wǎng)絡(luò)層),部署在了阿里云上,便成為了最早的DRDS。
上云的開(kāi)始--使用云,也服務(wù)云
值得一提的是,DRDS上云的方式放到現(xiàn)在看,也是非常時(shí)髦的。
像阿里云的普通用戶一樣,它也擁有一個(gè)阿里云的賬號(hào)(只不過(guò)這個(gè)賬號(hào)有上萬(wàn)億的授信額度),使用這個(gè)賬號(hào)的AK/SK,調(diào)用阿里云各個(gè)產(chǎn)品的Open API來(lái)進(jìn)行各種操作。
例如,創(chuàng)建實(shí)例時(shí),會(huì)購(gòu)買ECS來(lái)進(jìn)行部署DRDS節(jié)點(diǎn);會(huì)購(gòu)買SLB搭在前面來(lái)做負(fù)載均衡;會(huì)購(gòu)買SLS服務(wù)用來(lái)存儲(chǔ)該實(shí)例的SQL審計(jì);會(huì)打通DRDS節(jié)點(diǎn)到用戶RDS的網(wǎng)絡(luò)等等。
這種形式的管控架構(gòu)目前被廣泛地運(yùn)用,充分地利用了云的優(yōu)勢(shì)。DRDS幾乎不需要關(guān)注資源問(wèn)題,也不需要自己維護(hù)庫(kù)存;像機(jī)器宕機(jī)這種問(wèn)題,ECS也能自動(dòng)地進(jìn)行遷移(連IP都不會(huì)發(fā)生變化),非常的便利。讓DRDS的研發(fā)團(tuán)隊(duì)可以將更多的精力放在提升產(chǎn)品本身的能力上。
DRDS一方面為阿里云上的用戶提供服務(wù),另一方面也作為阿里云的一個(gè)“普通用戶”,享受著云技術(shù)帶來(lái)的好處,還是非常有趣的。
在DRDS時(shí)期,我們?cè)趦?nèi)核側(cè)重點(diǎn)積累了以下技術(shù)能力:
SQL語(yǔ)義上與MySQL的兼容性
TDDL僅服務(wù)于內(nèi)部用戶,而淘寶的研發(fā)規(guī)范相對(duì)是比較嚴(yán)格的,應(yīng)用使用的SQL都是比較簡(jiǎn)單的類型,所以對(duì)SQL的處理是非常少的,簡(jiǎn)單說(shuō),它甚至不需要理解SQL的語(yǔ)義,僅做轉(zhuǎn)發(fā)即可。但云上用戶的需求五花八門,又存在大量遷移上云的存量應(yīng)用,對(duì)SQL兼容性要求變高了很多。這就要求我們要提供一個(gè)完整的SQL引擎。
DRDS相對(duì)于TDDL以及市面上一眾的分庫(kù)分表中間件,多了兩個(gè)關(guān)鍵組件:具備完整的算子體系的查詢優(yōu)化器與執(zhí)行器。它的目標(biāo)是無(wú)論SQL有多復(fù)雜,都要能夠正確理解其語(yǔ)義,并執(zhí)行出正確的結(jié)果。
這里有非常多需要長(zhǎng)期積累的工作。舉幾個(gè)例子:
- 任何一個(gè)MySQL支持的內(nèi)建函數(shù),都有可能是基于一個(gè)不能下推的結(jié)果進(jìn)行計(jì)算的,這就要求DRDS需要支持所有MySQL的內(nèi)建函數(shù),并且目標(biāo)與MySQL的行為一致。我們?cè)贒RDS內(nèi)實(shí)現(xiàn)了幾乎所有的這些函數(shù)(https://github.com/ApsaraDB/galaxysql/tree/main/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function)。早期我們有兩位同學(xué)花了數(shù)年時(shí)間來(lái)做這件事情,并且打磨至今。
- MySQL中支持大量的charset與collation,不同的組合會(huì)帶來(lái)不同的排序結(jié)果。如果我們要使用歸并排序的算子對(duì)MySQL層已經(jīng)局部有序的結(jié)果進(jìn)行歸并,則需要確保DRDS使用與MySQL一致的排序行為。實(shí)際上這里要求DRDS支持與MySQL行為一致的charset與collation系統(tǒng),例如我們實(shí)現(xiàn)的utf8mb4_general_ci:https://github.com/ApsaraDB/galaxysql/blob/main/polardbx-common/src/main/java/com/alibaba/polardbx/common/collation/Utf8mb4GeneralCiCollationHandler.java。
類似這樣的工作還有很多,例如類型系統(tǒng)(https://zhuanlan.zhihu.com/p/374130246)、sql_mode、時(shí)區(qū)系統(tǒng)、默認(rèn)值等等,繁瑣但必要。這些工作都很好地延續(xù)到了PolarDB-X中。
極致的下推優(yōu)化
將計(jì)算下推到與數(shù)據(jù)最近的地方,這是保證性能的一個(gè)最樸素的原則。
將MySQL作為一個(gè)分布式數(shù)據(jù)庫(kù)的存儲(chǔ)引擎,它實(shí)際上本身也具備很強(qiáng)的計(jì)算能力。特別相對(duì)于目前很多使用KV來(lái)作為存儲(chǔ)引擎的分布式數(shù)據(jù)庫(kù),它們大多只能做到Filter、函數(shù)的下推執(zhí)行。但MySQL卻支持完整的SQL執(zhí)行,將分片級(jí)的JOIN、子查詢、聚合等操作盡可能多地下推到MySQL上,是DRDS保證高性能的一個(gè)關(guān)鍵。
下表簡(jiǎn)單對(duì)比業(yè)界產(chǎn)品的一些優(yōu)化選擇,信息來(lái)自公開(kāi)文檔:
推多了會(huì)導(dǎo)致結(jié)果錯(cuò)誤,推少了會(huì)達(dá)不到最佳性能。DRDS的優(yōu)化器積累了大量下推優(yōu)化策略。這些優(yōu)化策略大多是沒(méi)有辦法憑空想象出來(lái)的,只有通過(guò)實(shí)際的場(chǎng)景案例,才能得到積累。詳見(jiàn):https://zhuanlan.zhihu.com/p/366312701
物理算子的豐富與MPP的執(zhí)行引擎
物理算子也就是指執(zhí)行器的各種算法,例如對(duì)于Join,我們支持HybridHashJoin、LookupJoin、NestedLoopJoin、SortMergeJoin、MaterializedSemiJoin等等算法。
DRDS最初僅支持單線程去執(zhí)行SQL,但這種執(zhí)行對(duì)復(fù)雜的SQL是不夠用的。我們先做了單機(jī)并行引擎(SMP),又發(fā)展到了現(xiàn)在的MPP引擎,https://zhuanlan.zhihu.com/p/346320114
同時(shí),執(zhí)行引擎還支持spill out(中間結(jié)果落盤的能力),即使只有15M內(nèi)存,也能跑通TPCH 1G的測(cè)試,詳見(jiàn):https://zhuanlan.zhihu.com/p/363435372
這些能力的積累與突破,極大地提升了PolarDB-X在面對(duì)復(fù)雜的SQL的計(jì)算能力。
坎坷的分布式事務(wù)
分布式事務(wù),是繞不開(kāi)的一個(gè)問(wèn)題。
對(duì)于中間件類型的產(chǎn)品來(lái)說(shuō),我們有一個(gè)很基本的假設(shè):使用標(biāo)準(zhǔn)的MySQL,避免對(duì)MySQL做侵入性的修改;即使修改,也應(yīng)該是插件化的。
不修改MySQL,這導(dǎo)致我們很長(zhǎng)一段時(shí)間都沒(méi)有很好地實(shí)現(xiàn)分布式事務(wù)。
我們前前后后走過(guò)的一些彎路:
- 像傳統(tǒng)中間件一樣,禁止分布式事務(wù)。但這個(gè)對(duì)應(yīng)用的改造成本太高了;
- 使用柔性事務(wù),很長(zhǎng)一段時(shí)間我們使用GTS(原名TXC)這樣的第三方組件來(lái)實(shí)現(xiàn)分布式事務(wù)。這種方案需要對(duì)不同的SQL根據(jù)語(yǔ)義來(lái)實(shí)現(xiàn)回滾語(yǔ)句,SQL兼容性很差;
- 使用GTM的方案。GTM本質(zhì)是一個(gè)單點(diǎn),并且GTM與Coordinator之間要做大量的數(shù)據(jù)交互,性能太差,不可能作為一個(gè)默認(rèn)使用的事務(wù)策略。所以我們看使用GTM方案的“數(shù)據(jù)庫(kù)”,它一定有很嚴(yán)苛的使用條件(例如要求應(yīng)用盡量避免分布式事務(wù)、默認(rèn)關(guān)閉強(qiáng)一致等);
- XA事務(wù),早期的MySQL對(duì)XA支持的很弱,BUG很多(實(shí)際上現(xiàn)在的MySQL對(duì)于XA的BUG依然很多),例如宕機(jī)恢復(fù)流程很容易因?yàn)閄A掛掉。并且XA事務(wù)無(wú)法解決讀的可見(jiàn)性問(wèn)題,與單機(jī)事務(wù)的行為不兼容。
事務(wù)系統(tǒng)是一個(gè)與存儲(chǔ)層密切相關(guān)的事情,從PolarDB-X的探索來(lái)看,不對(duì)MySQL做深度修改,是不可能做出性能、功能都符合要求的分布式事務(wù)的。這是所有中間件類產(chǎn)品都無(wú)法解決的問(wèn)題,也是中間件與數(shù)據(jù)庫(kù)根本性的差異。
繞不開(kāi)的分區(qū)鍵
從DRDS的第一個(gè)用戶開(kāi)始,就一直要回答一個(gè)問(wèn)題,我的表怎么選分區(qū)鍵?
從做“高吞吐”、“高并發(fā)”的業(yè)務(wù)系統(tǒng)角度來(lái)看,要求表和SQL帶上有業(yè)務(wù)特征的分區(qū)鍵是非常合理的一件事情。全部下推到存儲(chǔ)層,避免產(chǎn)生跨機(jī)的查詢、事務(wù),做到這些才能保證做到最佳的性能,這是性能的天花板。
問(wèn)題是,雖然這樣做上限很高(高到淘寶雙十一0點(diǎn)的業(yè)務(wù)高峰也可以很絲滑),但:
- 這種改造成本是非常高的,很多時(shí)候分區(qū)鍵是很難選的。例如很多電商系統(tǒng)的訂單表會(huì)有兩個(gè)查詢維度,賣家和買家,選哪個(gè)當(dāng)分區(qū)鍵;
- 不是所有的業(yè)務(wù)系統(tǒng)(或者說(shuō)不是所有的表和SQL)都值得花這么大的代價(jià)去改造的,只有核心系統(tǒng)中的核心邏輯才需要做這種細(xì)致的改造;
- 拆分鍵選錯(cuò)了,會(huì)導(dǎo)致下限極低。對(duì)于數(shù)據(jù)庫(kù)來(lái)說(shuō),提供比較高的上限和提供不太低的下限同樣重要。
自然,我們想知道,什么樣的技術(shù),才能讓你“忘掉”分區(qū)鍵這個(gè)東西呢?
數(shù)據(jù)庫(kù)時(shí)代(2019~)
透明分布式之路
是否需要強(qiáng)制應(yīng)用在意分區(qū)鍵的概念,是中間件與數(shù)據(jù)庫(kù)的關(guān)鍵性區(qū)別之一。
1)分區(qū)鍵與全局索引
廣義的“分區(qū)鍵”的概念,其實(shí)并不是分布式數(shù)據(jù)庫(kù)特有的。
我們?cè)趩螜C(jī)數(shù)據(jù)庫(kù)中,例如MySQL中,數(shù)據(jù)存儲(chǔ)成了一棵一棵B樹(shù)。如果一個(gè)表只有主鍵,那它只有一棵B樹(shù),例如:
CREATE TABLE t1(
id INT,
name CHAR(32),
addr TEXT,
PRIMARY KEY (id)
)
這個(gè)表唯一的B樹(shù)是按照主鍵(id)進(jìn)行排序的。如果我們的查詢條件中帶了id的等值條件例如where id=14,那么就可以在這棵樹(shù)上快速的定位到這個(gè)id對(duì)應(yīng)的記錄在哪里;反之,則要進(jìn)行全表掃描。
B樹(shù)用于排序的Key,通過(guò)二分查找可以定位到一個(gè)葉子節(jié)點(diǎn);分區(qū)鍵通過(guò)哈?;蛘逺ange上的二分查找,可以定位到一個(gè)分片??梢钥闯鏊鼈兌际菫榱四芸焖俚囟ㄎ坏綌?shù)據(jù)。
如果我們要對(duì)上面的表做where name='Megan'來(lái)查詢,在MySQL中,我們并不需要將name設(shè)為主鍵。更加自然的方式是,在name上創(chuàng)建一個(gè)二級(jí)索引:
CREATE INDEX idx ON t1(name)
每個(gè)二級(jí)索引在MySQL中都是一棵獨(dú)立的B Tree,其用于排序的Key就是二級(jí)索引的列。
也就是說(shuō),當(dāng)前t1這張表,有兩顆B Tree了,主鍵一棵,idx一棵,分別是:
id->name,addr
name->id
當(dāng)使用where name='Megan'進(jìn)行查詢時(shí),會(huì)先訪問(wèn)idx這顆B樹(shù),根據(jù)name='Megan'定位到葉子節(jié)點(diǎn),獲取到id的值,再使用id的值到主鍵那顆B樹(shù)上,找到完整的記錄。
二級(jí)索引實(shí)際上是通過(guò)冗余數(shù)據(jù),使用空間與提升寫入的成本,換取了查詢的性能。
同時(shí),二級(jí)索引的維護(hù)代價(jià)并不是非常的高,一般情況下可以放心地在一個(gè)表上創(chuàng)建若干個(gè)二級(jí)索引。
同理,在分布式數(shù)據(jù)庫(kù)中,想讓你“忘掉”分區(qū)鍵這個(gè)東西,唯一的方法就是使用分布式二級(jí)索引,也稱為全局索引(Global Index)。并且這個(gè)全局索引需要做到高效、廉價(jià)、與傳統(tǒng)二級(jí)索引的兼容度高。
全局二級(jí)索引同樣也是一種數(shù)據(jù)冗余。例如,當(dāng)執(zhí)行一條SQL:
INSERT INTO t1 (id,name,addr) VALUES (1,"meng","hz");
如果orders表上有seller_id這個(gè)全局二級(jí)索引,可以簡(jiǎn)單理解為,我們會(huì)分別往主鍵與seller_id兩個(gè)全局索引中執(zhí)行這個(gè)insert,一共寫入兩條記錄:
INSERT INTO t1 (id,name,addr) VALUES (1,"meng","hz");
INSERT INTO idx (id,name) VALUES (1,"meng");
其中t1主鍵索引的分區(qū)鍵是id,idx的分區(qū)鍵是name。
同時(shí),由于這兩條記錄大概率不會(huì)在一個(gè)DN上,為了保證這兩條記錄的一致性,我們需要把這兩次寫入封裝到一個(gè)分布式事務(wù)內(nèi)(這與單機(jī)數(shù)據(jù)庫(kù)中,二級(jí)索引通過(guò)單機(jī)事務(wù)來(lái)寫入是類似的)。
當(dāng)我們所有的DML操作都通過(guò)分布式事務(wù)來(lái)對(duì)全局索引進(jìn)行維護(hù),二級(jí)索引和主鍵索引就能夠一直保持一致的狀態(tài)了。
好像全局索引聽(tīng)起來(lái)也很簡(jiǎn)單?實(shí)則不然。
2)全局索引與分布式事務(wù)
索引一定要是強(qiáng)一致的,例如:
- 不能寫索引表失敗了,但是寫主表成功了,導(dǎo)致索引表中缺數(shù)據(jù);
- 同一時(shí)刻去讀索引表與主表,看到的記錄應(yīng)該是一樣的,不能讀到一邊已提交,一邊未提交的結(jié)果。
- ...
這里對(duì)索引的一致性要求,實(shí)際上就是對(duì)分布式事務(wù)的要求。
由于全局索引的引入,100%的事務(wù)都會(huì)是分布式事務(wù),對(duì)分布式事務(wù)的要求和“強(qiáng)依賴分區(qū)鍵類型的分布式數(shù)據(jù)庫(kù)”完全不同了,要求變得更高:
- 至少需要做到SNAPSHOT ISOLATION以上的隔離級(jí)別,不然行為和單機(jī)MySQL差異會(huì)很大,會(huì)有非常大的數(shù)據(jù)一致性風(fēng)險(xiǎn)。目前常見(jiàn)的方案是HLC、TrueTime、TSO、GTM方案,如果某數(shù)據(jù)庫(kù)沒(méi)有使用這些技術(shù),則需要仔細(xì)甄別;
- 100%的分布式事務(wù)相比TPCC模型10%的分布式事務(wù),對(duì)性能的要求更高,HLC、TSO、TrueTime方案都能做到比較大的事務(wù)容量,相對(duì)而言,GTM由于更重,其上限要遠(yuǎn)遠(yuǎn)低于同為單點(diǎn)方案的TSO(TSO雖然是單點(diǎn),但由于有Grouping的優(yōu)化,容量可以做的很大);
- 即使用了TSO/HLC等方案,優(yōu)化也要到位,例如典型的1PC、Async Commit等優(yōu)化。不然維護(hù)索引增加的響應(yīng)時(shí)間會(huì)很難接受。
3)與單機(jī)索引的兼容性
此外,單機(jī)數(shù)據(jù)庫(kù)中,索引有一些看起來(lái)非常自然的行為,也是需要去兼容的。
例如:
- 能通過(guò)DDL語(yǔ)句直接創(chuàng)建索引,而不是需要各種各樣的周邊工具來(lái)完成。
- 前綴查詢,單機(jī)數(shù)據(jù)庫(kù)中,索引是可以很好地支持前綴查詢的,全局索引應(yīng)該如何去解這類問(wèn)題?
- 熱點(diǎn)問(wèn)題(Big Key問(wèn)題),單機(jī)數(shù)據(jù)庫(kù)中,如果一個(gè)索引選擇度不高(例如在性別上創(chuàng)建了索引),除了稍微有些浪費(fèi)資源外,不會(huì)有什么太嚴(yán)重的問(wèn)題;但是對(duì)于分布式數(shù)據(jù)庫(kù),這個(gè)選擇度低的索引會(huì)變成一個(gè)熱點(diǎn),導(dǎo)致整個(gè)集群的部分熱點(diǎn)節(jié)點(diǎn)成為整個(gè)系統(tǒng)的瓶頸。全局索引需要有相應(yīng)的方法去解決此類問(wèn)題。
索引的創(chuàng)建速度,索引回表的性能,索引的功能上的限制,聚簇索引,索引的存儲(chǔ)成本等等,其實(shí)也都極大的影響了全局索引的使用體驗(yàn),這里鑒于篇幅原因,就不繼續(xù)展開(kāi)了。
4)索引的數(shù)量
對(duì)全局索引的這些要求,本質(zhì)來(lái)源于全局索引的數(shù)量。
透明性做得好的數(shù)據(jù)庫(kù),所有索引都會(huì)是全局索引,其全局索引的數(shù)量會(huì)非常的多(正如單機(jī)數(shù)據(jù)庫(kù)中一個(gè)表一個(gè)庫(kù)的二級(jí)索引數(shù)量一樣)。數(shù)量多了,要求才會(huì)變高。
而,這些沒(méi)有全做好的分布式數(shù)據(jù)庫(kù),即使有全局索引,你會(huì)發(fā)現(xiàn)它們給出的用法依然會(huì)是強(qiáng)依賴分區(qū)鍵的用法。
它們會(huì)讓創(chuàng)建全局索引這件事,變成一個(gè)可選的、特別的事情。這樣業(yè)務(wù)在使用全局索引的時(shí)候會(huì)變得非常慎重。自然,全局索引的數(shù)量會(huì)變得非常有限。
當(dāng)全局索引的數(shù)量與使用場(chǎng)景被嚴(yán)格限制之后,上述做的不好的缺點(diǎn)也就變得沒(méi)那么重要了。
5)面向索引選擇的查詢優(yōu)化器
我們知道,數(shù)據(jù)庫(kù)的優(yōu)化器核心工作機(jī)制在于:
- 枚舉可能的執(zhí)行計(jì)劃
- 找到這些執(zhí)行計(jì)劃中代價(jià)最低的
例如一個(gè)SQL中涉及三張表,在只考慮左深樹(shù)的情況下:
- 在沒(méi)有全局索引的時(shí)候,可以簡(jiǎn)單理解為,執(zhí)行計(jì)劃的空間主要體現(xiàn)在這三張表的JOIN的順序,其空間大小大致為3x2x1=6。執(zhí)行計(jì)劃的空間相對(duì)是較小的,優(yōu)化器判斷這6個(gè)執(zhí)行計(jì)劃的代價(jià)也會(huì)容易很多。(當(dāng)然優(yōu)化器還有很多工作,例如分區(qū)裁剪等等,這些優(yōu)化有沒(méi)有索引都要做,就不多說(shuō)了)。
- 在有全局索引的時(shí)候,情況就復(fù)雜多了。假設(shè)每個(gè)表都有3個(gè)全局索引,那執(zhí)行計(jì)劃空間的大小大致會(huì)變成(3x3)x(2x3)x(1x3)=162,這個(gè)復(fù)雜度會(huì)急劇的上升。相應(yīng)的,對(duì)優(yōu)化器的要求就會(huì)高得多。優(yōu)化器需要考慮更多的統(tǒng)計(jì)信息,才能選擇出更優(yōu)的執(zhí)行計(jì)劃;需要做更多的剪枝,才能在更短的時(shí)間內(nèi)完成查詢優(yōu)化。
所以我們可以看到,在沒(méi)有全局索引的“分布式數(shù)據(jù)庫(kù)”或者一些中間件產(chǎn)品中,其優(yōu)化器是很羸弱的,大多是RBO的,它們根本就不需要一個(gè)強(qiáng)大的優(yōu)化器,更多的優(yōu)化內(nèi)容實(shí)際上被單機(jī)優(yōu)化器給替代了。
PolarDB-X提供了使用代價(jià)模型的優(yōu)化器:https://zhuanlan.zhihu.com/p/370372242
在MySQL上實(shí)現(xiàn)強(qiáng)一致、高性能的分布式事務(wù)
為了做一個(gè)透明的分布式數(shù)據(jù)庫(kù),最關(guān)鍵的就是全局索引以及全局索引依賴的分布式事務(wù)了。中間件時(shí)代的探索已經(jīng)告訴我們,要做強(qiáng)一致、高性能的分布式事務(wù),一定要對(duì)存儲(chǔ)(MySQL)做深度的修改。
我們選擇的是使用全局MVCC(TSO)+2PC(XA)的方案。
MySQL的單機(jī)MVCC中包含了start_timestamp(也就是MySQL中的trx_id),為了實(shí)現(xiàn)全局MVCC,需要做幾件核心的事情:
- 提供一個(gè)全局的時(shí)間戳生成器TSO,https://zhuanlan.zhihu.com/p/360160666
- 使用TSO生成的全局時(shí)間戳替換掉單機(jī)生成的trx_id
- 引入commit_timestamp(同樣由TSO生成),使用strat_timestamp與commit_timestamp來(lái)進(jìn)行可見(jiàn)性的判斷,非常的高效
https://zhuanlan.zhihu.com/p/355413022。不使用在節(jié)點(diǎn)之間交換活躍事物鏈表或者GTM這種代價(jià)非常大的方案。
PolarDB-X中的事務(wù)流程:
InnoDB中的記錄格式的修改,我們稱之為L(zhǎng)izard事務(wù)系統(tǒng),詳見(jiàn):https://developer.aliyun.com/article/795058
我們還有其他一些文章來(lái)介紹PolarDB-X分布式事務(wù)的實(shí)現(xiàn):
- PolarDB-X 強(qiáng)一致分布式事務(wù)原理
(https://zhuanlan.zhihu.com/p/329978215)
- PolarDB-X 分布式事務(wù)的實(shí)現(xiàn)(一)
(https://zhuanlan.zhihu.com/p/338535541)
有了分布式事務(wù)與全局索引后,PolarDB-X正式從中間件轉(zhuǎn)型成了一個(gè)分布式數(shù)據(jù)庫(kù)。
PolarDB-X的透明分布式
PolarDB-X實(shí)現(xiàn)了非常優(yōu)秀的分布式事務(wù)與全局索引,滿足上文提到了對(duì)全局索引的要求,做到了透明分布式。
在透明分布式模式下(CREATE DATABASE中指定mode='auto'),所有的索引都是全局索引,應(yīng)用無(wú)需關(guān)心分區(qū)鍵的概念。
例如,我們的建表語(yǔ)句,與單機(jī)MySQL完全一致,并不需要指定分區(qū)鍵:
create table orders (
id bigint,
buyer_id varchar(128) comment '買家',
seller_id varchar(128) comment '賣家',
primary key(id),
index sdx(seller_id),
index bdx(buyer_id)
)
創(chuàng)建全局索引也與單機(jī)MySQL創(chuàng)建二級(jí)索引的體驗(yàn)一致,全程是Online的:
CREATE INDEX idx_seller_id ON orders (seller_id);
PolarDB-X的全局索引是強(qiáng)一致的,其數(shù)據(jù)一致性體驗(yàn)與單機(jī)MySQL沒(méi)有明顯差異,提供了符合MySQL語(yǔ)義的RC與RR的隔離級(jí)別。
同時(shí),PolarDB-X在索引的維護(hù)、優(yōu)化器上也做了大量的工作,確保索引能高效的創(chuàng)建、維護(hù),優(yōu)化器能正確地生成使用索引的執(zhí)行計(jì)劃。
PolarDB-X的分區(qū)算法,也能很好地處理索引中產(chǎn)生的熱點(diǎn)、數(shù)據(jù)傾斜等問(wèn)題,參考:https://zhuanlan.zhihu.com/p/424174858
自動(dòng)(透明)決定下限,手動(dòng)決定上限
按透明與手動(dòng)來(lái)劃分市面上常見(jiàn)的分布式數(shù)據(jù)庫(kù):
- 透明的分布式數(shù)據(jù)庫(kù)的典型代表:TiDB、CockroachDB。
- 手動(dòng)的分布式數(shù)據(jù)庫(kù)典型代表:OceanBase、YugabyteDB。
是否透明的分布式數(shù)據(jù)一定比手動(dòng)的要好呢?
對(duì)于只提供透明用法的數(shù)據(jù)庫(kù),遷移成本會(huì)比較低,初步體驗(yàn)會(huì)比較好。但進(jìn)入深水區(qū)后,由于不可避免的會(huì)大量的使用分布式事務(wù),在核心場(chǎng)景中,性能往往是達(dá)不到要求的(或者同樣的性能需要更高的成本),并且缺少消除分布式事務(wù)、更充分的計(jì)算下推等優(yōu)化手段。
對(duì)于只提供手動(dòng)用法的數(shù)據(jù)庫(kù),雖然設(shè)計(jì)良好的分區(qū)鍵使得理論上能夠做到性能最優(yōu),但使用門檻會(huì)大幅增加(10%核心表設(shè)計(jì)分區(qū)鍵也就算了,剩下的90%非核心表也要設(shè)計(jì)分區(qū)鍵)。
我們認(rèn)為,無(wú)論是純透明還是純手動(dòng)的分布式數(shù)據(jù)庫(kù),都無(wú)法很好地滿足業(yè)務(wù)對(duì)試用成本和性能兼顧的要求。
PolarDB-X除了提供了透明模式,也完整的支持了分區(qū)表的語(yǔ)法,并提供了Join Group/Table Group、分區(qū)在線變更等工具,讓應(yīng)用在需要極致性能的情況下,能將事務(wù)、計(jì)算更多的下推到存儲(chǔ)節(jié)點(diǎn)。
PolarDB-X是市面上唯一能夠做到同時(shí)提供透明與手動(dòng)兩種模式的分布式數(shù)據(jù)庫(kù),我們推薦大多場(chǎng)景使用透明模式,之后對(duì)核心業(yè)務(wù)場(chǎng)景進(jìn)行壓測(cè),并使用分區(qū)表語(yǔ)法對(duì)這些場(chǎng)景做手動(dòng)的優(yōu)化,以達(dá)到最高的性能。
使用Paxos協(xié)議做到RPO=0
中間件對(duì)接的MySQL普遍使用主備架構(gòu),這種方式最大的問(wèn)題就是會(huì)丟數(shù)據(jù),甚至?xí)r間長(zhǎng)了是一個(gè)必然的事情。(常在河邊走,哪能不濕鞋呢?)
經(jīng)過(guò)數(shù)據(jù)庫(kù)圈子這幾年的科普,基本大家都知道了需要使用一些一致性協(xié)議,例如Paxos和Raft才能做到不丟數(shù)據(jù)。這些協(xié)議實(shí)際上并不是什么秘密了,甚至數(shù)據(jù)庫(kù)圈子都有一個(gè)段子:“現(xiàn)在校招的學(xué)生都要能手?jǐn)]Paxos了”。
門檻并不在協(xié)議本身上,而在于如何與MySQL結(jié)合后的穩(wěn)定性與性能。穩(wěn)定性,只有經(jīng)過(guò)大規(guī)模的驗(yàn)證,踩過(guò)足夠多的坑,才能獲得。
PolarDB-X所使用的的Paxos協(xié)議是源于阿里內(nèi)部的X-Paxos,可以這樣說(shuō),阿里內(nèi)部的MySQL數(shù)據(jù)庫(kù),已經(jīng)不存在主備模式了,100%的使用X-Paxos。這代表它經(jīng)歷了上萬(wàn)個(gè)MySQL集群以及各種大促的驗(yàn)證,具備極高的可靠性。
我們有幾篇文章想寫介紹X-Paxos:
- PolarDB-X 一致性共識(shí)協(xié)議 —— X-Paxos:https://zhuanlan.zhihu.com/p/302845832
- PolarDB-X 存儲(chǔ)架構(gòu)之“基于Paxos的最佳生產(chǎn)實(shí)踐”:https://zhuanlan.zhihu.com/p/315596644
完全兼容MySQL的Binlog協(xié)議
要利用MySQL生態(tài)的資源,非常重要的一點(diǎn)是能夠使用MySQL生態(tài)的工具,將數(shù)據(jù)流向下游。業(yè)內(nèi)常見(jiàn)的方案里:
- 中間件類產(chǎn)品,需要用戶去訂閱每個(gè)MySQL的Binlog,由用戶自行解決這中間的各種運(yùn)維問(wèn)題(例如DDL問(wèn)題,不同的分表名要做合并等),非常的繁瑣;
- 分布式數(shù)據(jù)庫(kù)類產(chǎn)品,這些大多提供自己的CDC能力,例如OceanBase、TiDB,但他們的格式并非MySQL的Binlog格式,無(wú)法直接使用MySQL生態(tài)。
PolarDB-X是市面上唯一一個(gè)提供完全兼容MySQL Binlog協(xié)議的分布式數(shù)據(jù)庫(kù),用戶可以使用任何開(kāi)源的MySQL Binlog訂閱、解析工具(例如Canal)來(lái)對(duì)接PolarDB-X的Binlog。
這極大地提升了PolarDB-X的易用性。詳見(jiàn):
PolarDB-X 如何兼容MySQL Binlog 協(xié)議和參數(shù),https://zhuanlan.zhihu.com/p/512114589
PolarDB-X 全局 Binlog 解讀,https://zhuanlan.zhihu.com/p/369115822
下一個(gè)五年
我們對(duì)未來(lái)的PolarDB-X充滿想象,希望她能變成一個(gè)更好的數(shù)據(jù)庫(kù)。雖然有很多的不確定性,不過(guò)有一些事情是我們會(huì)持續(xù)去做的。
最重要的,我們會(huì)堅(jiān)持在MySQL生態(tài)上,并且堅(jiān)持在基于MySQL作為存儲(chǔ)節(jié)點(diǎn)構(gòu)建分布式數(shù)據(jù)庫(kù)這條技術(shù)路線上。我們認(rèn)為這是我們相對(duì)于其他分布式數(shù)據(jù)庫(kù)的一個(gè)非常關(guān)鍵的差異。與MySQL的兼容其實(shí)分為功能兼容與性能兼容,使用分布式KV等技術(shù)方案,也許能在功能上兼容MySQL,但是很難做到與MySQL性能上的兼容。MySQL是一個(gè)具備全功能的存儲(chǔ),將大量的事務(wù)與計(jì)算下推到存儲(chǔ)節(jié)點(diǎn),是分布式數(shù)據(jù)庫(kù)做到高性能的關(guān)鍵。
業(yè)內(nèi)提供全局索引的分布式數(shù)據(jù)庫(kù),全局索引的性能(寫入和查詢)與單機(jī)數(shù)據(jù)庫(kù)中索引的性能和行為普遍都有一定的差距,縮小這個(gè)差距,便能提升分布式數(shù)據(jù)庫(kù)的下限。對(duì)于PolarDB-X來(lái)說(shuō),這個(gè)差距主要來(lái)自于CN與DN(MySQL)之間的交互鏈路過(guò)長(zhǎng),有很多冗余的操作(MySQL Server層的線程連接模型、MySQL優(yōu)化器、Parser等)。我們會(huì)通過(guò)使用RPC協(xié)議與MySQL進(jìn)行交互、做薄MySQL Server層等方式來(lái)進(jìn)一步提升PolarDB-X全局索引的性能。
自動(dòng)的負(fù)載均衡能夠極大的降低分布式數(shù)據(jù)庫(kù)的使用門檻,PolarDB-X的一些特性(手動(dòng)與自動(dòng)兼顧、Join能夠下推等),使得這件事情相對(duì)于不支持這些特性的數(shù)據(jù)庫(kù)有一些額外的難度(一把淚,但我們可以解決),這塊還需要一些時(shí)間進(jìn)行打磨。
降本增效是這兩年比較火的一個(gè)話題,PolarDB-X即將OSS歸檔的能力,能夠自動(dòng)的將歷史數(shù)據(jù)轉(zhuǎn)儲(chǔ)到OSS上,并能通過(guò)和在線數(shù)據(jù)一樣的SQL接口進(jìn)行訪問(wèn),也支持使用Spark等開(kāi)源大數(shù)據(jù)工具對(duì)轉(zhuǎn)儲(chǔ)的OSS文件直接進(jìn)行分析等操作。詳見(jiàn):https://zhuanlan.zhihu.com/p/477664175
HTAP是分布式數(shù)據(jù)庫(kù)領(lǐng)域比較熱門的主題,各數(shù)據(jù)庫(kù)廠商提出了各種各樣的方案。但從現(xiàn)有的HTAP實(shí)現(xiàn)來(lái)看,性能、隔離性、成本三者處于一種比較矛盾的狀態(tài)(有些數(shù)據(jù)庫(kù)會(huì)使用列存副本,性能OK,但很貴;有些數(shù)據(jù)庫(kù)在HA使用的備節(jié)點(diǎn)來(lái)做分析,性能和隔離性就會(huì)差一些),離理想中的HTAP差距甚遠(yuǎn)。我們也會(huì)在這個(gè)領(lǐng)域做持續(xù)性的投入,希望能探索出一種能滿足大多數(shù)業(yè)務(wù)場(chǎng)景的HTAP的形態(tài)出來(lái)。
提供異地多活(全球化等概念)在數(shù)據(jù)庫(kù)層面更原生的支持。支持淘寶的異地多活使我們團(tuán)隊(duì)在這個(gè)領(lǐng)域積累了大量的經(jīng)驗(yàn)(相信沒(méi)有人比我們懂的更多)。實(shí)際上PolarDB-X是國(guó)內(nèi)少有的落地大型異地多活項(xiàng)目的數(shù)據(jù)庫(kù)(其中一個(gè)還是民生級(jí)的系統(tǒng)),我們希望能把這些經(jīng)驗(yàn)變成數(shù)據(jù)庫(kù)的原生能力,減少異地多活系統(tǒng)對(duì)外部組件的依賴,將它變得更為普世。
分享名稱:十年磨一劍,云原生分布式數(shù)據(jù)庫(kù)PolarDB-X的核心技術(shù)演化
標(biāo)題URL:http://fisionsoft.com.cn/article/ccscihs.html


咨詢
建站咨詢
