隨著大數(shù)據(jù)這個(gè)概念的興起以及真實(shí)需求在各個(gè)行業(yè)的落地,很多人都熱衷于討論分布式數(shù)據(jù)庫(kù),今天就這個(gè)話題,主要分為三部分:第一部分講一下分布式數(shù)據(jù)庫(kù)的過去和現(xiàn)狀,希望大家能對(duì)這個(gè)領(lǐng)域有一個(gè)全面的了解;第二部分講一下TiDB的架構(gòu)以及最近的一些進(jìn)展;最后結(jié)合我們開發(fā)TiDB過程中的一些思考講一下分布式數(shù)據(jù)庫(kù)未來可能的趨勢(shì)。
一、分布式數(shù)據(jù)庫(kù)的歷史和現(xiàn)狀
1、從單機(jī)數(shù)據(jù)庫(kù)說起
關(guān)系型數(shù)據(jù)庫(kù)起源自1970年代,其最基本的功能有兩個(gè):
把數(shù)據(jù)存下來;
滿足用戶對(duì)數(shù)據(jù)的計(jì)算需求。
第一點(diǎn)是最基本的要求,如果一個(gè)數(shù)據(jù)庫(kù)沒辦法把數(shù)據(jù)安全完整存下來,那么后續(xù)的任何功能都沒有意義。當(dāng)滿足第一點(diǎn)后,用戶緊接著就會(huì)要求能夠使用數(shù)據(jù),可能是簡(jiǎn)單的查詢,比如按照某個(gè)Key來查找Value;也可能是復(fù)雜的查詢,比如要對(duì)數(shù)據(jù)做復(fù)雜的聚合操作、連表操作、分組操作。往往第二點(diǎn)是一個(gè)比第一點(diǎn)更難滿足的需求。
在數(shù)據(jù)庫(kù)發(fā)展早期階段,這兩個(gè)需求其實(shí)不難滿足,比如有很多優(yōu)秀的商業(yè)數(shù)據(jù)庫(kù)產(chǎn)品,如Oracle/DB2。在1990年之后,出現(xiàn)了開源數(shù)據(jù)庫(kù)MySQL和PostgreSQL。這些數(shù)據(jù)庫(kù)不斷地提升單機(jī)實(shí)例性能,再加上遵循摩爾定律的硬件提升速度,往往能夠很好地支撐業(yè)務(wù)發(fā)展。
接下來,隨著互聯(lián)網(wǎng)的不斷普及特別是移動(dòng)互聯(lián)網(wǎng)的興起,數(shù)據(jù)規(guī)模爆炸式增長(zhǎng),而硬件這些年的進(jìn)步速度卻在逐漸減慢,人們也在擔(dān)心摩爾定律會(huì)失效。在此消彼長(zhǎng)的情況下,單機(jī)數(shù)據(jù)庫(kù)越來越難以滿足用戶需求,即使是將數(shù)據(jù)保存下來這個(gè)最基本的需求。
2、分布式數(shù)據(jù)庫(kù)
所以2005年左右,人們開始探索分布式數(shù)據(jù)庫(kù),帶起了NoSQL這波浪潮。這些數(shù)據(jù)庫(kù)解決的首要問題是單機(jī)上無法保存全部數(shù)據(jù),其中以HBase/Cassadra/MongoDB為代表。為了實(shí)現(xiàn)容量的水平擴(kuò)展,這些數(shù)據(jù)庫(kù)往往要放棄事務(wù),或者是只提供簡(jiǎn)單的KV接口。存儲(chǔ)模型的簡(jiǎn)化為存儲(chǔ)系統(tǒng)的開發(fā)帶來了便利,但是降低了對(duì)業(yè)務(wù)的支撐。
(1)NoSQL的進(jìn)擊
HBase是其中的典型代表。HBase是Hadoop生態(tài)中的重要產(chǎn)品,Google BigTable的開源實(shí)現(xiàn),所以這里先說一下BigTable。
BigTable是Google內(nèi)部使用的分布式數(shù)據(jù)庫(kù),構(gòu)建在GFS的基礎(chǔ)上,彌補(bǔ)了分布式文件系統(tǒng)對(duì)于小對(duì)象的插入、更新、隨機(jī)讀請(qǐng)求的缺陷。HBase也按照這個(gè)架構(gòu)實(shí)現(xiàn),底層基于HDFS。HBase本身并不實(shí)際存儲(chǔ)數(shù)據(jù),持久化的日志和SST file存儲(chǔ)在HDFS上,Region Server通過 MemTable 提供快速的查詢,寫入都是先寫日志,后臺(tái)進(jìn)行Compact,將隨機(jī)寫轉(zhuǎn)換為順序?qū)憽?shù)據(jù)通過 Region 在邏輯上進(jìn)行分割,負(fù)載均衡通過調(diào)節(jié)各個(gè)Region Server負(fù)責(zé)的Region區(qū)間實(shí)現(xiàn),Region在持續(xù)寫入后,會(huì)進(jìn)行分裂,然后被負(fù)載均衡策略調(diào)度到多個(gè)Region Server上。
前面提到了,HBase本身并不存儲(chǔ)數(shù)據(jù),這里的Region僅是邏輯上的概念,數(shù)據(jù)還是以文件的形式存儲(chǔ)在HDFS上,HBase并不關(guān)心副本個(gè)數(shù)、位置以及水平擴(kuò)展問題,這些都依賴于HDFS實(shí)現(xiàn)。和BigTable一樣,HBase提供行級(jí)的一致性,從CAP理論的角度來看,它是一個(gè)CP的系統(tǒng),并且沒有更進(jìn)一步提供 ACID 的跨行事務(wù),也是很遺憾。
HBase的優(yōu)勢(shì)在于通過擴(kuò)展Region Server可以幾乎線性提升系統(tǒng)的吞吐,及HDFS本身就具有的水平擴(kuò)展能力,且整個(gè)系統(tǒng)成熟穩(wěn)定。但HBase依然有一些不足。首先,Hadoop使用Java開發(fā),GC延遲是一個(gè)無法避免問題,這對(duì)系統(tǒng)的延遲造成一些影響。另外,由于HBase本身并不存儲(chǔ)數(shù)據(jù),和HDFS之間的交互會(huì)多一層性能損耗。第三,HBase和BigTable一樣,并不支持跨行事務(wù),所以在Google內(nèi)部有團(tuán)隊(duì)開發(fā)了MegaStore、Percolator這些基于BigTable的事務(wù)層。Jeff Dean承認(rèn)很后悔沒有在BigTable中加入跨行事務(wù),這也是Spanner出現(xiàn)的一個(gè)原因。
(2)RDMS的救贖
除了NoSQL之外,RDMS系統(tǒng)也做了不少努力來適應(yīng)業(yè)務(wù)的變化,也就是關(guān)系型數(shù)據(jù)庫(kù)的中間件和分庫(kù)分表方案。做一款中間件需要考慮很多,比如解析 SQL,解析出ShardKey,然后根據(jù)ShardKey分發(fā)請(qǐng)求,再合并結(jié)果。另外在中間件這層還需要維護(hù)Session及事務(wù)狀態(tài),而且大多數(shù)方案并不支持跨shard的事務(wù),這就不可避免地導(dǎo)致了業(yè)務(wù)使用起來會(huì)比較麻煩,需要自己維護(hù)事務(wù)狀態(tài)。此外,還有動(dòng)態(tài)的擴(kuò)容縮容和自動(dòng)的故障恢復(fù),在集群規(guī)模越來越大的情況下,運(yùn)維和DDL的復(fù)雜度是指數(shù)級(jí)上升。
國(guó)內(nèi)開發(fā)者在這個(gè)領(lǐng)域有過很多的著名的項(xiàng)目,比如阿里的Cobar、TDDL,后來社區(qū)基于Cobar改進(jìn)的MyCAT,360開源的Atlas等,都屬于這一類中間件產(chǎn)品。在中間件這個(gè)方案上有一個(gè)知名的開源項(xiàng)目是Youtube的Vitess,這是一個(gè)集大成的中間件產(chǎn)品,內(nèi)置了熱數(shù)據(jù)緩存、水平動(dòng)態(tài)分片、讀寫分離等,但這也造成了整個(gè)項(xiàng)目非常復(fù)雜。
另外一個(gè)值得一提的是PostgreSQL XC這個(gè)項(xiàng)目,其整體的架構(gòu)有點(diǎn)像早期版本的OceanBase,由一個(gè)中央節(jié)點(diǎn)來處理協(xié)調(diào)分布式事務(wù),數(shù)據(jù)分散在各個(gè)存儲(chǔ)節(jié)點(diǎn)上,應(yīng)該是目前PG 社區(qū)最好的分布式擴(kuò)展方案,不少人在基于這個(gè)項(xiàng)目做自己的系統(tǒng)。
3、NewSQL的發(fā)展
2012~2013年Google 相繼發(fā)表了Spanner和F1兩套系統(tǒng)的論文,讓業(yè)界第一次看到了關(guān)系模型和NoSQL的擴(kuò)展性在一個(gè)大規(guī)模生產(chǎn)系統(tǒng)上融合的可能性。 Spanner 通過使用硬件設(shè)備(GPS時(shí)鐘+原子鐘)巧妙地解決時(shí)鐘同步的問題,而在分布式系統(tǒng)里,時(shí)鐘正是最讓人頭痛的問題。Spanner的強(qiáng)大之處在于即使兩個(gè)數(shù)據(jù)中心隔得非常遠(yuǎn),也能保證通過TrueTime API獲取的時(shí)間誤差在一個(gè)很小的范圍內(nèi)(10ms),并且不需要通訊。Spanner的底層仍然基于分布式文件系統(tǒng),不過論文里也說是可以未來優(yōu)化的點(diǎn)。
Google的內(nèi)部的數(shù)據(jù)庫(kù)存儲(chǔ)業(yè)務(wù),大多是3~5副本,重要的數(shù)據(jù)需要7副本,且這些副本遍布全球各大洲的數(shù)據(jù)中心,由于普遍使用了Paxos,延遲是可以縮短到一個(gè)可以接受的范圍(寫入延遲100ms以上),另外由Paxos帶來的Auto-Failover能力,更是讓整個(gè)集群即使數(shù)據(jù)中心癱瘓,業(yè)務(wù)層都是透明無感知的。F1是構(gòu)建在Spanner之上,對(duì)外提供了SQL接口,F(xiàn)1是一個(gè)分布式MPP SQL層,其本身并不存儲(chǔ)數(shù)據(jù),而是將客戶端的SQL翻譯成對(duì)KV的操作,調(diào)用Spanner來完成請(qǐng)求。
Spanner和F1的出現(xiàn)標(biāo)志著第一個(gè)NewSQL在生產(chǎn)環(huán)境中提供服務(wù),將下面幾個(gè)功能在一套系統(tǒng)中提供:
SQL支持
ACID事務(wù)
水平擴(kuò)展
Auto Failover
多機(jī)房異地容災(zāi)
正因?yàn)榫邆淙绱硕嗟恼T人特性,在Google內(nèi)部,大量的業(yè)務(wù)已經(jīng)從原來的 BigTable切換到Spanner之上。相信這對(duì)業(yè)界的思路會(huì)有巨大的影響,就像當(dāng)年的Hadoop一樣,Google的基礎(chǔ)軟件的技術(shù)趨勢(shì)是走在社區(qū)前面的。
Spanner/F1論文引起了社區(qū)的廣泛的關(guān)注,很快開始出現(xiàn)了追隨者。第一個(gè)團(tuán)隊(duì)是CockroachLabs做的CockroachDB。CockroachDB的設(shè)計(jì)和Spanner很像,但是沒有選擇TrueTime API ,而是使用HLC(Hybrid logical clock),也就是NTP +邏輯時(shí)鐘來代替TrueTime時(shí)間戳,另外CockroachDB選用Raft做數(shù)據(jù)復(fù)制協(xié)議,底層存儲(chǔ)落地在RocksDB中,對(duì)外的接口選擇了PG協(xié)議。
CockroachDB的技術(shù)選型比較激進(jìn),比如依賴了HLC來做事務(wù),時(shí)間戳的精確度并沒有辦法做到10ms內(nèi)的延遲,所以Commit Wait需要用戶自己指定,其選擇取決于用戶的NTP服務(wù)時(shí)鐘誤差,這點(diǎn)對(duì)于用戶來說非常不友好。當(dāng)然 CockroachDB的這些技術(shù)選擇也帶來了很好的易用性,所有邏輯都在一個(gè)組件中,部署非常簡(jiǎn)單,這個(gè)是非常大的優(yōu)點(diǎn)。
另一個(gè)追隨者就是我們做的TiDB。這個(gè)項(xiàng)目已經(jīng)開發(fā)了兩年時(shí)間,當(dāng)然在開始動(dòng)手前我們也準(zhǔn)備了很長(zhǎng)時(shí)間。接下來我會(huì)介紹一下這個(gè)項(xiàng)目。
二、TiDB的架構(gòu)和最近進(jìn)展
TiDB本質(zhì)上是一個(gè)更加正統(tǒng)的Spanner和F1實(shí)現(xiàn),并不CockroachDB那樣選擇將SQL和KV融合,而是像Spanner和F1一樣選擇分離。
這樣分層的思想也是貫穿整個(gè)TiDB項(xiàng)目始終的,對(duì)于測(cè)試,滾動(dòng)升級(jí)以及各層的復(fù)雜度控制會(huì)比較有優(yōu)勢(shì),另外TiDB選擇了MySQL協(xié)議和語法的兼容,MySQL社區(qū)的ORM框架、運(yùn)維工具,直接可以應(yīng)用在TiDB上,另外和 Spanner一樣,TiDB是一個(gè)無狀態(tài)的MPP SQL Layer,整個(gè)系統(tǒng)的底層是依賴 TiKV 來提供分布式存儲(chǔ)和分布式事務(wù)的支持,TiKV的分布式事務(wù)模型采用的是Google Percolator的模型,但是在此之上做了很多優(yōu)化,Percolator的優(yōu)點(diǎn)是去中心化程度非常高,整個(gè)繼續(xù)不需要一個(gè)獨(dú)立的事務(wù)管理模塊,事務(wù)提交狀態(tài)這些信息其實(shí)是均勻分散在系統(tǒng)的各個(gè)key的meta中,整個(gè)模型唯一依賴的是一個(gè)授時(shí)服務(wù)器,在我們的系統(tǒng)上,極限情況這個(gè)授時(shí)服務(wù)器每秒能分配 400w以上個(gè)單調(diào)遞增的時(shí)間戳,大多數(shù)情況基本夠用了(畢竟有Google量級(jí)的場(chǎng)景并不多見),同時(shí)在TiKV中,這個(gè)授時(shí)服務(wù)本身是高可用的,也不存在單點(diǎn)故障的問題。
上面是TiKV的架構(gòu)圖。TiKV和CockroachDB一樣也是選擇了Raft作為整個(gè)數(shù)據(jù)庫(kù)的基礎(chǔ),不一樣的是,TiKV整體采用Rust語言開發(fā),作為一個(gè)沒有GC和 Runtime的語言,在性能上可以挖掘的潛力會(huì)更大。不同TiKV實(shí)例上的多個(gè)副本一起構(gòu)成了一個(gè)Raft Group,PD負(fù)責(zé)對(duì)副本的位置進(jìn)行調(diào)度,通過配置調(diào)度策略,可以保證一個(gè)Raft Group的多個(gè)副本不會(huì)保存在同一臺(tái)機(jī)器/機(jī)架/機(jī)房中。
除了核心的TiDB、TiKV之外,我們還提供了不少易用的工具,便于用戶做數(shù)據(jù)遷移和備份。比如我們提供的Syncer,不但能將單個(gè)MySQL實(shí)例中的數(shù)據(jù)同步到TiDB,還能將多個(gè)MySQL實(shí)例中的數(shù)據(jù)匯總到一個(gè)TiDB集群中,甚至是將已經(jīng)分庫(kù)分表的數(shù)據(jù)再合庫(kù)合表。這樣數(shù)據(jù)的同步方式更加靈活好用。
TiDB目前即將發(fā)布RC3版本,預(yù)計(jì)六月份能夠發(fā)布GA版本。在即將到來的 RC3版本中,對(duì)MySQL兼容性、SQL優(yōu)化器、系統(tǒng)穩(wěn)定性、性能做了大量的工作。對(duì)于OLTP場(chǎng)景,重點(diǎn)優(yōu)化寫入性能。另外提供了權(quán)限管理功能,用戶可以按照MySQL的權(quán)限管理方式控制數(shù)據(jù)訪問權(quán)限。對(duì)于OLAP場(chǎng)景,也對(duì)優(yōu)化器做了大量的工作,包括更多語句的優(yōu)化、支持SortMergeJoin算子、IndexLookupJoin算子。另外對(duì)內(nèi)存使用也做了大量的優(yōu)化,一些場(chǎng)景下,內(nèi)存使用下降75%。
除了TiDB本身的優(yōu)化之外,我們還在做一個(gè)新的工程,名字叫TiSpark。簡(jiǎn)單來講,就是讓Spark更好地接入TiDB?,F(xiàn)在其實(shí)Spark已經(jīng)可以通過JDBC接口讀取TiDB中的數(shù)據(jù),但是這里有兩個(gè)問題:1. 只能通過單個(gè)TiDB節(jié)點(diǎn)讀取數(shù)據(jù)且數(shù)據(jù)需要從TiKV中經(jīng)過 TiDB 中轉(zhuǎn)。2. 不能和Spark的優(yōu)化器相結(jié)合,我們期望能和Spark的優(yōu)化器整合,將Filter、聚合能通過TiKV的分布式計(jì)算能力提速。這個(gè)項(xiàng)目已經(jīng)開始開發(fā),預(yù)計(jì)近期開源,五月份就能有第一個(gè)版本。
三、分布式數(shù)據(jù)庫(kù)的未來趨勢(shì)
關(guān)于未來,我覺得未來的數(shù)據(jù)庫(kù)會(huì)有幾個(gè)趨勢(shì),也是TiDB項(xiàng)目追求的目標(biāo):
1、數(shù)據(jù)庫(kù)會(huì)隨著業(yè)務(wù)云化,未來一切的業(yè)務(wù)都會(huì)跑在云端,不管是私有云或者公有云,運(yùn)維團(tuán)隊(duì)接觸的可能再也不是真實(shí)的物理機(jī),而是一個(gè)個(gè)隔離的容器或者「計(jì)算資源」,這對(duì)數(shù)據(jù)庫(kù)也是一個(gè)挑戰(zhàn),因?yàn)閿?shù)據(jù)庫(kù)天生就是有狀態(tài)的,數(shù)據(jù)總是要存儲(chǔ)在物理的磁盤上,而數(shù)據(jù)移動(dòng)的代價(jià)比移動(dòng)容器的代價(jià)可能大很多。
2、多租戶技術(shù)會(huì)成為標(biāo)配,一個(gè)大數(shù)據(jù)庫(kù)承載一切的業(yè)務(wù),數(shù)據(jù)在底層打通,上層通過權(quán)限,容器等技術(shù)進(jìn)行隔離,但是數(shù)據(jù)的打通和擴(kuò)展會(huì)變得異常簡(jiǎn)單,結(jié)合第一點(diǎn)提到的云化,業(yè)務(wù)層可以再也不用關(guān)心物理機(jī)的容量和拓?fù)?,只需要認(rèn)為底層是一個(gè)無窮大的數(shù)據(jù)庫(kù)平臺(tái)即可,不用再擔(dān)心單機(jī)容量和負(fù)載均衡等問題。
3、OLAP和OLTP業(yè)務(wù)會(huì)融合,用戶將數(shù)據(jù)存儲(chǔ)進(jìn)去后,需要比較方便高效的方式訪問這塊數(shù)據(jù),但是OLTP和OLAP在SQL優(yōu)化器/執(zhí)行器這層的實(shí)現(xiàn)一定是千差萬別的。以往的實(shí)現(xiàn)中,用戶往往是通過ETL工具將數(shù)據(jù)從OLTP數(shù)據(jù)庫(kù)同步到OLAP數(shù)據(jù)庫(kù),這一方面造成了資源的浪費(fèi),另一方面也降低了OLAP的實(shí)時(shí)性。對(duì)于用戶而言,如果能使用同一套標(biāo)準(zhǔn)的語法和規(guī)則來進(jìn)行數(shù)據(jù)的讀寫和分析,會(huì)有更好的體驗(yàn)。
4、在未來分布式數(shù)據(jù)庫(kù)系統(tǒng)上,主從日志同步這樣落后的備份方式會(huì)被Multi-Paxos / Raft這樣更強(qiáng)的分布式一致性算法替代,人工的數(shù)據(jù)庫(kù)運(yùn)維在管理大規(guī)模數(shù)據(jù)庫(kù)集群時(shí)是不可能的,所有的故障恢復(fù)和高可用都將是高度自動(dòng)化的。