分布式數(shù)據(jù)庫是不同的
今天的話題有兩層含義,第一層是說相對于我們所熟知的集中式數(shù)據(jù)庫來說,分布式數(shù)據(jù)庫是與之不同的。在做數(shù)據(jù)庫選型的時候,我們要充分的了解其間的不同,才能做出較為科學的決策。我想很多數(shù)據(jù)庫從業(yè)人員都了解其中的不同,不幸的是,他們不是數(shù)據(jù)庫選型的決策者,大多數(shù)決策者并不了解這一點。
關(guān)于分布式數(shù)據(jù)庫與集中式數(shù)據(jù)庫的不同,我上周已經(jīng)發(fā)文討論過了,今天我要講的是另外一個問題,那就是不同的分布式數(shù)據(jù)庫產(chǎn)品也是不同的。
2013年,我和一些準備開發(fā)一款分布式數(shù)據(jù)庫的朋友在討論這個產(chǎn)品的時候,實際上大家對數(shù)據(jù)庫,特別是分布式數(shù)據(jù)庫都不太了解。我們給這款數(shù)據(jù)庫提出的目標是:
圖片
首先是超大規(guī)模,都分布式數(shù)據(jù)庫了,肯定是要能解決集中式數(shù)據(jù)庫的容量不足的問題的,因此超大是必須的,超大規(guī)模的數(shù)據(jù)庫可以解決存儲容量、計算容量與超大規(guī)模計算的速度等一系列問題;可動態(tài)擴展,不夠用了就擴節(jié)點;無需備份,自動容災(zāi),自動故障切換;有了上面這一條,那么保證永遠在線,永不出錯也就不是難事了。不過實際上今天看來,當時對數(shù)據(jù)庫的了解太粗淺了,十年過去了,我還沒看到這個數(shù)據(jù)庫產(chǎn)品出現(xiàn)。
目前的分布式數(shù)據(jù)庫產(chǎn)品種類繁多,技術(shù)路線也各有不同,我今天不準備對其做準確的分類,而是從幾個小角度來看看這些數(shù)據(jù)庫產(chǎn)品之間的不同。首先是從存算分離和對等分布式這兩種最為典型流派說起。分布式數(shù)據(jù)庫要么采用存算分離架構(gòu),要么采用對等分布式架構(gòu)。其典型產(chǎn)品就是TiDB和OceanBase。
存算分離,顧名思義,其計算引擎和存儲引擎是完全分離的,計算引擎負責SQL的執(zhí)行,存儲引擎負責管理被存儲的數(shù)據(jù)。徹底的存算分離的數(shù)據(jù)庫,其最典型的特點是創(chuàng)建數(shù)據(jù)表的時候不需要SHARDING KEY,數(shù)據(jù)存儲的分片是數(shù)據(jù)庫內(nèi)部自動管理的。當SQL引擎需要訪問某個數(shù)據(jù)的時候,會根據(jù)元數(shù)據(jù)信息以及分片邏輯,自動找到所需要訪問的數(shù)據(jù)。存算分離的數(shù)據(jù)庫,計算節(jié)點可能只有一個,也可以是一個讀寫節(jié)點,多個只讀節(jié)點,甚至也可以是多個全功能對等的讀寫節(jié)點。比如TiDB,其TiDB節(jié)點是計算節(jié)點,多個計算節(jié)點是對等模式的,全功能讀寫的。其TiKV是存儲節(jié)點,負責存儲所有的數(shù)據(jù)。
對于存算分離的分布式數(shù)據(jù)庫,計算節(jié)點生成SQL的執(zhí)行樹后,會把算子下推到多個存儲節(jié)點進行并行的數(shù)據(jù)掃描或者訪問。算子的并行化程度以及能夠下推的粒度決定了執(zhí)行的效率。因此此類數(shù)據(jù)庫的性能取決于SQL執(zhí)行計劃的水平與可下推的算子的粒度。
有些存算分離的數(shù)據(jù)庫,其存儲節(jié)點是一個獨立的數(shù)據(jù)庫實例,這種情況下,大部分算子是以子SQL的形式下推到存儲節(jié)點的,其效率相對是較低的。當然,數(shù)據(jù)庫廠商也可以就其數(shù)據(jù)庫引擎的核心進行改造,使之能夠接受更細小的算子的下推,從而提高執(zhí)行性能。有些基于Postgresql等開源代碼的分布式數(shù)據(jù)庫,比如Gaussdb就是這么做的。
談到Gaussdb,這里就多說幾句,實際上Gaussdb是一種存算分離的分布式數(shù)據(jù)庫,其CN是計算節(jié)點,DN是存儲節(jié)點。不過Gaussdb與TiDB雖然說都是采用存算分離,但是其實現(xiàn)方式差異很大。Gaussdb的CN/DN實際上都包含了一個全功能的RDBMS實例,甚至客戶端可以直接連接到DN上去做SQL的執(zhí)行。而TiDB的計算與存儲引擎的功能是完全分離的,必須二者合體才能完成SQL執(zhí)行的任務(wù)。對于Gaussdb來說,一個SQL可以將其子查詢?nèi)嫦掳l(fā)到DN上,CN只做簡單的匯聚,CN也可以下推更細粒度的算子到DN上,由CN完成更多的計算?;贕aussdb的架構(gòu),如果我們要將一張表分布到多個DN上,那么我們就必須指定Sharding Key。
那么這兩種存算分離架構(gòu)哪個更優(yōu)呢?還真的不太好說,TiDB可以像我們使用普通的集中式數(shù)據(jù)庫一樣來使用分布式數(shù)據(jù)庫,這方面TiDB似乎更勝一籌,不過實際上并非如此。因為TiDB的完全存算分離,導致了計算節(jié)點的本地數(shù)據(jù)緩沖無法實現(xiàn)了,所有的數(shù)據(jù)訪問都不能直接從本地緩沖里獲取,而都必須通過存儲節(jié)點獲取。這導致了一些對延時要求較高的OLTP系統(tǒng)的性能無法滿足,這就是所謂的“穩(wěn)定的慢”。
對于一些復雜的表關(guān)聯(lián),大查詢,其性能雖然說與架構(gòu)相關(guān),但是最終決定性能的還是CBO優(yōu)化器的執(zhí)行計劃的效率,以及算子分解與并行下推的能力。因此存算分離的分布式數(shù)據(jù)庫,能夠以何種粒度下推算子與優(yōu)化器的功力決定了最終的性能。對于存儲節(jié)點是一個獨立的數(shù)據(jù)庫實例的分布式數(shù)據(jù)庫而言,在最初的技術(shù)實現(xiàn)上,肯定下推的只是子SQL。下推比SQL粒度更小的算子必須在SQL引擎的核心上做工作,因此對技術(shù)要求更高。當然隨著產(chǎn)品的發(fā)展,這種工作是必須要做的。不過目前很多采用此類架構(gòu)的分布式數(shù)據(jù)庫的存儲引擎采用了MySQL,對于此類數(shù)據(jù)庫的核心代碼的修改,如果不開源,是否違反了GPL協(xié)議,我一直百思不得其解。
分布式數(shù)據(jù)庫的另外一個主要流派就是對等分布式,其代表是OceanBase。此類數(shù)據(jù)庫是采用分片技術(shù)的,每個分片是一個完整的rdbms實例,具有計算引擎,并帶有存儲引擎,用于管理本地的數(shù)據(jù)??蛻舳诉B接到任何一個分片,都可以執(zhí)行SQL,不需要通過一個計算節(jié)點。這種架構(gòu)的缺點是如果要把一張表打散到分布式集群中,這張表必須指定Sharding Key。不過優(yōu)點是每個節(jié)點都可以通過本地緩存來提高本地數(shù)據(jù)的訪問性能。
今天的討論我主要想讓讀者了解,沒有完美的分布式數(shù)據(jù)庫架構(gòu),如果我們要來看一個分布式數(shù)據(jù)庫的水平,不僅僅要看起實現(xiàn)架構(gòu),更重要的是要看其SQL引擎、CBO優(yōu)化器和分布式執(zhí)行器的能力。誰家的產(chǎn)品把這些做好了,就能脫穎而出。