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