NoSQL先驅(qū)RethinkDB倒掉后,借此來看開源新型數(shù)據(jù)庫NewSQL的未來
作者:黃東旭
NoSQL 先驅(qū)之一的 RethinkDB 的關(guān)張大吉,RethinkDB這個事情本身我就不多做評論了,現(xiàn)在這個時機去分析不免有馬后炮的嫌疑,今天我想借著這個引子談?wù)勑滦蛿?shù)據(jù)庫的未來。
最近數(shù)據(jù)庫圈的一個比較大的事件是 NoSQL 先驅(qū)之一的 RethinkDB 的關(guān)張大吉,RethinkDB這個事情本身我就不多做評論了,現(xiàn)在這個時機去分析不免有馬后炮的嫌疑,今天我想借著這個引子談?wù)勑滦蛿?shù)據(jù)庫的未來。
縱觀過去十年數(shù)據(jù)庫的發(fā)展,其實是相當迅速,隨著互聯(lián)網(wǎng)的發(fā)展以及業(yè)務(wù)數(shù)據(jù)量的不斷膨脹,大家漸漸發(fā)現(xiàn)傳統(tǒng)的單機RDBMS 開始出現(xiàn)一些瓶頸,很多業(yè)務(wù)的模型也和當初數(shù)據(jù)庫設(shè)計的場景不太一樣,一個最典型的思潮就是反范式設(shè)計,通過適當?shù)臄?shù)據(jù)冗余來減小 JOIN 帶來的開銷,當初 *-NF 的設(shè)計目的是盡可能的減小數(shù)據(jù)冗余,但現(xiàn)在的硬件和存儲容量遠非當年可比,而且存儲介質(zhì)也在慢慢發(fā)生變化,從磁帶到磁盤到閃存,甚至最近慢慢開始變成另一個異構(gòu)的分布式存儲系統(tǒng) (如 Google F1, TiDB),RDBMS 本身也需要進化。
在 NoSQL 蓬勃發(fā)展的這幾年也是 Web 和移動端崛起的幾年,但是在 NoSQL 中反范式的設(shè)計是需要以付出一致性為代價,不過這個世界的業(yè)務(wù)多種多樣,大家漸漸發(fā)現(xiàn)將一致性交給業(yè)務(wù)去管理會極大的增加業(yè)務(wù)的復(fù)雜度,但是在數(shù)據(jù)庫層做又沒有太好的可以 Scale 的方案,SPOF 問題和單機性能及帶寬瓶頸會成為懸在業(yè)務(wù)頭上的達摩克利斯之劍。
NewSQL 的出現(xiàn)就是為了解決擴展性和一致性之間的矛盾,我所理解的 NewSQL 主要還是面向 OLTP 業(yè)務(wù)和輕量級的OLAP業(yè)務(wù),大型復(fù)雜的OLAP 數(shù)據(jù)庫暫時不在本文討論的范圍。對于NewSQL 來說,我覺得應(yīng)該需要明確一下必備的性質(zhì),什么樣的數(shù)據(jù)庫才能稱之為NewSQL,在我看來,應(yīng)該有以下幾點必備的特性:
- SQL
- ACID Transaction, 支持跨行事務(wù)
- Auto-scale
- Auto-failover
SQL 一切為了兼容性!兼容性!兼容性! SQL 的支持是和之前 NoSQL 從接口上最大的不同點, 但是在一個分布式系統(tǒng)上支持 SQL 和在單機 RDBMS 上也是完全不一樣的,更關(guān)鍵的是如何更好的利用多個節(jié)點的計算能力,生成更好的執(zhí)行計劃,將計算邏輯盡可能的均攤到多個存儲節(jié)點上,設(shè)計這樣一個 SQL engine 的更像是在做一個分布式計算框架,考慮的側(cè)重點和單機上的查詢引擎是不一樣的,畢竟網(wǎng)絡(luò)的開銷和延遲是單機數(shù)據(jù)庫之前完全不需要考慮的。
不過 從最近幾年社區(qū)的實現(xiàn)來看,尤其是一些 OLAP 的系統(tǒng),已經(jīng)有不少優(yōu)秀的分布式SQL 實現(xiàn) ,比如: Hive, Impala,Presto, SparkSQL 等優(yōu)秀的開源項目。雖然 OLTP 的 SQL engine 和 OLAP 的側(cè)重點有所不同,但是很多技術(shù)是相通的,但是一些單機 RDBMS 的 SQL 是很難直接應(yīng)用在分布式環(huán)境下的,比如存儲過程和視圖等。正如剛才提到的,越來越多的業(yè)務(wù)開始接受反范式的設(shè)計,甚至很多新的業(yè)務(wù)都禁止使用存儲過程和外鍵等,這是一個好的現(xiàn)象。
ACID Transaction 對于 OLTP 類型的 NewSQL 來說,最重要的特點我認為是需要支持 ACID 的跨行事務(wù),其實隔離級別和跨行事務(wù)是個好東西,能用更少的代碼寫出正確的程序,這個交給業(yè)務(wù)程序員寫基本費時費力還很難寫對,但在分布式場景下支持分布式事務(wù)需要犧牲點什么。
本身分布式 MVCC 并不是太難做,在 Google BigTable / Spanner 這樣的系統(tǒng)中顯式的多版本已經(jīng)是標配,那么其實犧牲掉的是一定的延遲,因為在分布式場景中實現(xiàn)分布式事務(wù)在生產(chǎn)環(huán)境中基本就只有兩階段提交的一種辦法,不過呢,考慮到 Multi-Paxos 或者 Raft 這樣的復(fù)制協(xié)議總是要 有延遲的,兩階段提交所帶來的 contention cost 相比復(fù)制其實也不算太多,對于一個分布式數(shù)據(jù)庫來說我們優(yōu)化的目標永遠是吞吐。延遲問題也可以通過緩存和靈活降低隔離級別等方法 搞定。
很多用戶在進行架構(gòu)設(shè)計的時候,通常會避免分布式事務(wù),但是這其實將很多復(fù)雜度轉(zhuǎn)移給了業(yè)務(wù)層,而且實現(xiàn)正確的事務(wù)語義是非常復(fù)雜的事情,對于開發(fā)者的要求還蠻高的,之前其實沒有太多的辦法,因為幾乎沒有一個方案能在數(shù)據(jù)庫層面上支持事務(wù),但是有些對一致性的要求很高的業(yè)務(wù)對此仍然是繞不開的。
就如同 Google 的 Senior Fellow Engineer,Jeff Dean 在 去年的一個會議上提到,作為工程師最后悔的事情就是沒有在 BigTable 上支持跨行事務(wù),以 至于在隨后的 10 多年,Google 內(nèi)部的團隊前赴后繼的在 BigTable 上造了多套事務(wù)的輪子以支撐業(yè)務(wù),不過這個遺憾在 Spanner 中已經(jīng)彌補了,也算是 happy ending。
其實 Spanner 的例子是非常好的,而且我認為 Google Spanner 及 F1 是第一個在線上大規(guī)模使用的 NewSQL 系統(tǒng),很多經(jīng)驗和設(shè)計我們這些后來者是可以借鑒的。我認為,從使用者的角度來 說,濫用事務(wù)帶來的性能問題不能作為在數(shù)據(jù)庫層面上不支持的理由,很多場景如果使用得當 ,能極大的降低業(yè)務(wù)開發(fā)的復(fù)雜度。
Scale 作為一個現(xiàn)代的數(shù)據(jù)庫,可擴展性我覺得是排在第一位的,而且這里的可擴展性值得好好說一 下,目前關(guān)系型數(shù)據(jù)庫的擴展方案上,基本只有分庫分表和 PROXY 中間件兩種方案,但是這兩種方案并沒有辦法做到透明的彈性擴展,而且到達一定規(guī)模后的運維成本幾乎是指數(shù)級別上升,這也是大多數(shù)公司在微服務(wù)實踐的過程中遇到的最大障礙,服務(wù)可以很好的做到無狀態(tài)和解耦合,但是數(shù)據(jù)天然是有狀態(tài)的,比較理想的情況是有一個統(tǒng)一的,通用的存儲層,讓服務(wù)層能夠放開手腳。
彈性擴展的技術(shù)在很多 NoSQL 里已經(jīng)有過很好的實踐,目前比較成熟的 方案還是類 BigTable 式的 Region based 的方案,在 Key-Value 層面上實現(xiàn)水平擴展。另外值得一提的是,對于 NewSQL 這類需要支持 SQL 的數(shù)據(jù)庫而言,region based 的數(shù)據(jù)切分是目前唯一的方案, 因為 SQL 的查詢需要支持順序 Scan 的數(shù)據(jù)訪問方式,基于一致性哈希的方案很難支持高效的順序訪問。這
里隱含了一個假設(shè)就是真正能夠支持 Scale 的 NewSQL 架構(gòu)很難是基于中間件的方案,SQL above NoSQL 是目前來說唯一的可行方案,從 Google 的選型也能看出來。
基于中間件的方案的問題是中間件很難生成足夠高效的執(zhí)行計劃,而且底 層的多個數(shù)據(jù)庫實例之間并沒有辦法提供一個統(tǒng)一的事務(wù)語義,在執(zhí)行跨節(jié)點的 JOIN 或者事務(wù)的時候沒有辦法保證一致性,另外底層的數(shù)據(jù)庫實例(一般來說是 PostgreSQL 或者 MySQL) 本身并沒有原生的擴展方案,需要中間件層面上額外做大量的工作,這也是為什么中間件的方案很多,但是做完美非常困難。
Failover 目前大多數(shù)的數(shù)據(jù)庫的復(fù)制模型還是基于主從的方案,但是主從的方案本質(zhì)上來說是沒有辦法脫離人工運維的,所以這個模型是很難 Scale 的 。如果需要做 Auto failover,從庫何時提升成主庫,主庫是否完全下線,提升起來的從庫是否擁有最新的數(shù)據(jù)?尤其如果出現(xiàn)集群腦裂的 狀況,一旦 Auto failover 設(shè)計得不周全,甚至可能出現(xiàn)雙主的嚴重故障。
所以數(shù)據(jù)的一致性是需要 DBA 的人工介入保證,但是在數(shù)據(jù)量比較龐大的情況下,人工可運維的規(guī)模是有上限的,比如 Google 在 F1 之前,維護了一個 100 節(jié)點左右的 MySQL 中間件集群支持同樣的業(yè) 務(wù),在這個規(guī)模之下維護的成本就已經(jīng)非常高了,使得 Google 不惜以從零開始重新開發(fā)一個數(shù)據(jù)庫為代價。
從 Google 在 Spanner 和 F1 以及現(xiàn)在流行的開源 NewSQL 方案,比如 TiDB 和 CockroachDB 等可以看到,在復(fù)制模型上都沒有選擇主從的模型,而是選用了 Multi-Paxos 或者 Raft 這樣基于分布式選舉的復(fù)制協(xié)議。
Multi-Paxos (以下出于省略暫用 Paxos 來指代,但是實際上兩者有些不一樣,在本文特指 Multi-Paxos) 和 Raft 的原理由于篇幅原因就不贅述了,簡單來說,它們是高度自動化,強一 致的復(fù)制算法,在某節(jié)點故障的時候,支持完全自動和強一致的故障轉(zhuǎn)移和自我恢復(fù),這樣才能做到用戶層的透明,但是這里有一個技術(shù)的難點,即Scale 策略與這樣的復(fù)制協(xié)議的融合, 多個 Paxos / Raft Group 的分裂、合并以及調(diào)度,以及相關(guān)的測試。
這個技術(shù)的門檻比較高 ,實現(xiàn)起來的復(fù)雜度也比較高,但是作為一個 Scale 的數(shù)據(jù)庫來說,是一定要實現(xiàn)的,在目前的開源實現(xiàn)中,只有 PingCAP 的 TiDB 的成熟度和穩(wěn)定度是比較高的,有興趣的朋友可以參考 TiDB (github.com/pingcap/tidb) 的實現(xiàn)。
Failover 相關(guān)的另外一個話題是跨數(shù)據(jù)中心多活,這個基本上是所有分布式系統(tǒng)開發(fā)者心中的 圣杯。目前也是基本沒有方案,大多數(shù)的多活的方案還是同步熱備,而且很難在保證延遲的情 況下同時保持一致性,但是 Paxos 和 Raft based 的方案給多活提供了一種新的可能性,這類選舉算法,只要一個 paxos / raft group 內(nèi)的大多數(shù)節(jié)點復(fù)制成功,即可給客戶端返回成功。
舉一個簡單的例子,如果這個 group 內(nèi)有三個節(jié)點,分別在北京,廊坊,廣州的三個數(shù)據(jù)中心,對于傳統(tǒng)的強一致方案,一個在北京發(fā)起的寫入需要等待廣州的數(shù)據(jù)中心復(fù)制完畢,才能 給客戶端返回成功,但是對于 paxos 或者 raft 這樣的算法,其實延遲僅僅是北京和廊坊之間 數(shù)據(jù)中心的延遲,比傳統(tǒng)方案大大的降低了延遲,雖然對于帶寬的要求仍然很高,但是我覺得這是在數(shù)據(jù)庫層面上未來實現(xiàn)跨數(shù)據(jù)中心多活的一個趨勢和可行的方向。
按照 Google 在 Spanner 論文中的描述,Google 的數(shù)據(jù)中心分別位于美國西海岸,東海岸,以及中部,所以 總體的寫入延遲控制在半個美國的范圍內(nèi),還是可以接受的。
未來在哪里不妨把眼光稍微放遠一些,其實仔細想想 NewSQL 一直在嘗試解決問題是:擺脫人工運維束縛,存儲層實現(xiàn)真正的自生長,自維護,同時用戶可以以最自然的編程接口訪問和存儲數(shù)據(jù)。 當實現(xiàn)這點以后,業(yè)務(wù)才可以擺脫存儲的介質(zhì),容量的限制,而專注于邏輯實現(xiàn)。
大規(guī)模的分布式和多租戶是必然的選擇,其實這個目標和云的目標是很接近的,實際上數(shù)據(jù)庫是云不可或缺的一部分,不過現(xiàn)在的數(shù)據(jù)庫都太不 Cloud-Native 了,所以如何和云更緊密結(jié)合,更好的利用云的資源調(diào)度,如何對業(yè)務(wù)透明的同時無縫的在云上自我進化是我最近思考得比較多的問 題。在這個領(lǐng)域Google 是走在時代前沿的,從幾個 NewSQL 的開源實現(xiàn)者都不約而同的選 擇了 Spanner 和 F1 的模型上可以看得出來。
責任編輯:武曉燕
來源:
36大數(shù)據(jù)


























