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






























