開源資料庫的現狀

qiuyesuifeng發表於2016-10-11

資料庫作為業務的核心,是整個基礎軟體棧非常重要的一環。近幾年的開源社群,新的思想和方案層出不窮,我將總結一下近幾年一些主流的開源資料庫方案,及其背後的設計思想以及適用場景。本人才疏學淺如有遺漏或者錯誤請見諒。本次分享聚焦於資料庫即結構化資料儲存 OLTP 及 NoSQL 領域,不會涉及 OLAP、物件儲存以及分散式檔案系統。

開源 RDBMS 與網際網路的崛起 很長時間以來,關係型資料庫一直是大公司的專利,市場被 Oracle / DB2 等企業資料庫牢牢把持。但是隨著網際網路的崛起和開源社群的發展,上世紀九十年代 MySQL 1.0 的釋出,標誌著在關係型資料庫的領域,社群終於有了可選擇的方案。

✦MySQL

第一個介紹的單機 RDBMS 就是 MySQL。相信大多數朋友都已經對 MySQL 非常熟悉,基本上 MySQL 的成長史就是網際網路的成長史。我接觸的第一個 MySQL 版本是 MySQL 4.0,後來的 MySQL 5.5 更是經典——基本上所有的網際網路公司都在使用。MySQL 也普及了「可插拔」引擎這一概念,即針對不同的業務場景選用不同的儲存引擎,這也是 MySQL tuning 的一個重要方式。比如對於有事務需求的場景使用 InnoDB;對於併發讀取的場景 MyISAM 可能比較合適;但是現在我推薦絕大多數情況還是使用 InnoDB,畢竟 MySQL 5.6 後它已經成為了官方的預設引擎。MySQL 適用於幾乎所有需要持久化結構化資料的場景, 大多數朋友應該都知道,我就不贅述了。

另外值得一提的是 MySQL 5.6 中引入了多執行緒複製和 GTID,使得故障恢復和主從的運維變得比較方便。另外,MySQL 5.7(目前處於 GA 版本) 釋出了一個重大更新,主要是在讀寫效能和複製效能上有了長足的進步:在 5.6 版本中實現了 SCHEMA 級別的並行複製。不過意義不大,倒是 MariaDB 的多執行緒並行複製大放異彩,有不少人因為這個特性選擇 MariaDB。另外,MySQL 5.7 MTS 支援兩種模式,一種是和 5.6 一樣,另一種則是基於 binlog group commit 實現的多執行緒複製,也就是 MASTER 上同時提交的 binlog 在 SLAVE 端也可以同時被 apply,實現並行複製。如果有單機資料庫技術選型的朋友,基本上只需要考慮 MySQL 5.7 或者 MariaDB 就好了,而且 MySQL 5.6 和 5.7 由 Oracle 接手後,效能和穩定性都有了明顯的提升。

✦PostgreSQL

PostgreSQL 的歷史也非常悠久,其前身是 UCB 的 Ingres,主持這個專案的 Michael Stronebraker 於 2015 年獲得圖靈獎。後來該專案更名為 Post-Ingres,基於 BSD license 下開源。 1995 年幾個 UCB 的學生為 Post-Ingres 開發了 SQL 的介面,正式釋出了 PostgreSQL95,隨後一步步在開源社群中成長起來。和 MySQL 一樣,PostgreSQL 也是一個單機的關係型資料庫,但是與 MySQL 方便使用者過度擴充套件的 SQL 文法不一樣的是,PostgreSQL 的 SQL 支援非常強大,不管是內建型別、JSON 支援、GIS 型別以及對於複雜查詢的支援,PL/SQL 等都比 MySQL 強大得多,而且從程式碼質量上來看,PostgreSQL 的程式碼質量是優於 MySQL 的。另外,相對於 MySQL 5.7 以前的版本, PostgreSQL 的 SQL 優化器比 MySQL 強大很多,幾乎所有稍微複雜的查詢 PostgreSQL 的表現都優於 MySQL。

從近幾年的趨勢上來看,PostgreSQL 的勢頭也很強勁,我認為 PostgreSQL 的不足之處在於沒有 MySQL 那樣強大的社群和群眾基礎。MySQL 經過那麼多年的發展,積累了很多的運維工具和最佳實踐,但是 PostgreSQL 作為後起之秀,擁有更優秀的設計和更豐富的功能。PostgreSQL 9 以後的版本也足夠穩定,在做新專案技術選型的時候,是一個很好的選擇。另外也有很多新的資料庫專案是基於 PostgreSQL 原始碼的基礎上進行二次開發,比如 Greenplum 等。

我認為,單機資料庫的時代很快就會過去。摩爾定律帶來的硬體紅利總是有上限的,現代業務的資料規模、流量以及現代的資料科學對於資料庫的要求,單機已經很難滿足。比如,網路卡磁碟 IO 和 CPU 總有瓶頸,線上敏感的業務系統可能還得承擔 SPOF(單點故障) 的風險,主從複製模型在主掛掉時到底切還是不切?切了以後資料如何恢復?如果只是出現主從機器網路分割槽問題呢?甚至是監控環境出現網路分割槽問題呢?這些都是單機資料庫面臨的巨大挑戰。所以我的觀點是,無論單機效能多棒(很多令人乍舌的評測資料都是針對特定場景的優化,另外甚至有些都是本機不走網路,而大多數情況資料庫出現的第一個瓶頸其實是網路卡和併發連線……),隨著網際網路的蓬勃發展和移動網際網路的出現,資料庫系統迎來了第一次分散式的洗禮。

分散式時代:NoSQL 的復興和模型簡化的力量 在介紹 NoSQL 之前,我想提兩個公司,一個是 Google,另一個是 Amazon。

✦Google

Google 應該是第一個將分散式儲存技術應用到大規模生產環境的公司,同時也是在分散式系統上積累最深的公司,可以說目前工業界的分散式系統的工程實踐及思想大都來源於 Google。比如 2003 年的 GFS 開創了分散式檔案系統,2006 年的 Bigtable 論文開創了分散式鍵值系統,直接催生的就是 Hadoop 的生態;至於 2012 年發表論文的 Spanner 和 F1 更是一個指明未來關係型資料庫發展方向的里程碑式的專案,這個我們後續會說。

✦Amazon

另一個公司是 Amazon。2007 年發表的 Dynamo 的論文 嘗試引入了最終一致性的概念, WRN 的模型及向量時鐘的應用,同時將一致性 HASH、merkle tree 等當時一些很新潮的技術整合起來,正式標誌著 NoSQL 的誕生。NoSQL——對後來業界的影響非常也是很大,包括後來的 Cassandra、RiakDB、Voldemort 等資料庫都是基於 Dynamo 的設計發展起來的。

✦新思潮

另外這個時期(2006 年前後持續至今)一個比較重要的思潮就是資料庫(持久化)和快取開始有明確的分離——我覺得這個趨勢是從 memcached 開始的。隨著業務的併發越來越高,對於低延遲的要求也越來越高;另外一個原因是隨著記憶體越來越便宜,基於記憶體的儲存方案漸漸開始普及。當然記憶體快取方案也經歷了一個從單機到分散式的過程,但是這個過程相比關係型資料庫的進化要快得多。這是因為 NoSQL 的另外一個重要的標誌——資料模型的變化——大多 NoSQL 都拋棄了關係模型,選擇更簡單的鍵值或者文件型別進行儲存。資料結構和查詢介面都相對簡單,沒有了 SQL 的包袱,實現的難度會降低很多。另外 NoSQL 的設計幾乎都選擇犧牲掉複雜 SQL 的支援及 ACID 事務換取彈性擴充套件能力,也是從當時網際網路的實際情況出發:業務模型簡單、爆發性增長帶來的海量併發及資料總量爆炸、歷史包袱小、工程師強悍,等等。其中最重要的還是業務模型相對簡單。

✦嵌入式儲存引擎

在開始介紹具體的開源的完整方案前,我想介紹一下嵌入式儲存引擎們。

隨著 NoSQL 的發展,不僅僅快取和持久化儲存開始細分,再往後的儲存引擎也開始分化並走上前臺。之前很難想象一個儲存引擎獨立於資料庫直接對外提供服務,就像你不會直接拿著 InnoDB 或者 MyISAM 甚至一個 B-tree 出來用一樣(當然,bdb 這樣鼎鼎大名的除外)。人們基於這些開源的儲存引擎進行進一步的封裝,比如加上網路協議層、加上覆制機制等等,一步步構建出完整的風格各異的 NoSQL 產品。

這裡我挑選幾個比較著名的儲存引擎介紹一下。

✦TC

我最早接觸的是 Tokyo Cabinet(TC)。TC 相信很多人也都聽說過,TC 是由日本最大的社交網站 Mixi 開發並開源的一個混合 Key-Value 儲存引擎,其中包括 HASH Table 和 B+ Tree 的實現。但是這個引擎的一個缺陷是隨著資料量的膨脹,效能的下降會非常明顯,而且現在也基本不怎麼維護了,所以入坑請慎重。與於 TC 配合使用的 Tokyo Tyrant(TT) 是一個網路庫,為 TC 提供網路的介面使其變成一個資料庫服務,TT + TC 應該是比較早的 NoSQL 的一個嘗試。

✦LevelDB

在 2011 年,Google 開源了 Bigtable 的底層儲存引擎: LevelDB。LevelDB 是一個使用 C++ 開發的嵌入式的 Key-Value 儲存引擎,資料結構採用了 LSM-Tree,具體 LSM-Tree 的演算法分析可以很容易在網上搜尋到,我就不贅述了。其特點是,對於寫入極其友好,LSM 的設計避免了大量的隨機寫入;對於特定的讀也能達到不錯的效能(熱資料在記憶體中);另外 LSM-Tree 和 B-tree 一樣是支援有序 Scan 的;而且 LevelDB 是出自 Jeff Dean 之手,他的事蹟做分散式系統的朋友一定都知道,不知道的可以去 Google 搜一下。

LevelDB 擁有極好的寫效能,執行緒安全,BatcTCh Write 和 Snapshot 等特性,使其很容易的在上層構建 MVCC 系統或者事務模型,這對於資料庫來說非常重要。另外值得一說的是,Facebook 維護了一個活躍的 LevelDB 的分支,名為 RocksDB。RocksDB 在 LevelDB 上做了很多的改進,比如多執行緒 Compactor、分層自定義壓縮、多 MemTable 等。另外 RocksDB 對外暴露了很多 ConfigurationConfigration ,可以根據不同業務的形態進行調優;同時 Facebook 在內部正在用 RocksDB 來實現一個全新的 MySQL 儲存引擎:MyRocks,值得關注。RocksDB 的社群響應速度很快也很友好,實際上 PingCAP 也是 RocksDB 的社群貢獻者。我建議新的專案如果在 LevelDB 和 RocksDB 之間糾結的話,請果斷選擇 RocksDB。

✦B-tree 家族

當然,除了 LSM-Tree 外,B-tree 的家族也還是有很多不錯的引擎。首先大多數傳統的單機資料庫的儲存引擎都選擇了 B+Tree,B+Tree 對磁碟的讀比較友好,第三方儲存引擎比較著名的純 B+Tree 實現是 LMDB。首先 LMDB 選擇在記憶體映像檔案 (mmap) 實現 B+Tree,而且同時使用了 Copy-On-Write 實現了 MVCC 實現併發事務無鎖讀的能力,對於高併發讀的場景比較友好;同時因為使用的是 mmap 所以擁有跨程式讀取的能力。不過因為我並沒有在生產環境中使用過 LMDB ,所以並不能給出 LMDB 的一些缺陷,見諒。

✦混合引擎

還有一部分的儲存引擎選擇了多種引擎混合,比如最著名的應該是 WiredTiger,大概是 2014 年去年被 MongoDB 收購,現在成為了 MongoDB 的預設儲存引擎。WiredTiger 內部有 LSM-Tree 和 B-tree 兩種實現,對外提供相同的一套介面,根據業務的情況可自由選擇。另外一些特殊資料結構的儲存引擎在某些特殊場合下非常搶眼,比如極高壓縮比 TokuDB,採用了名為分形樹的資料結構,在維持一個可接受的讀寫壓力的情況下,能擁有 10 倍以上的壓縮率。

✦NoSQL

說完了幾個比較著名的儲存引擎,我們來講講比較著名的 NoSQL。在我的定義中,NoSQL 是 Not Only SQL 的縮寫,所以可能包含的範圍有記憶體資料庫,持久化資料庫等。總之就是和單機的關係型資料庫不一樣的結構化資料儲存系統。

我們先從快取開始。

✦memcached

前面提到了 memcached 應該是第一個大規模在業界使用的快取資料庫,memcached 的實現極其簡單,相當於將記憶體用作大的 HASH Table,只能在上面進行 get/set/ 計數器等操作,在此之上用 libevent 封裝了一層網路層和文字協議(也有簡單的二進位制協議),雖然支援一些 CAS 的操作,但是總體上來看,還是非常簡單的。但是 memcached 的記憶體利用率並不太高,這是這個因為 memcached 為了避免頻繁申請記憶體導致的記憶體碎片的問題,採用了自己實現的 slab allocator 的方式。即記憶體的分配都是一塊一塊的,最終儲存在固定長度的 chunk 上,記憶體最小的分配單元是 chunk,另外 libevent 的效能也並沒有優化到極致。但是這些缺點並不妨礙 memcached 成為當時的開源快取事實標準。(另外,八卦一下,memcached 的作者 Brad Fitzpatrick 現在在 Google,大家如果用 Golang 的話,Go 的官方 HTTP 包就是這哥們寫的,是個很高產的工程師)。

✦Redis

如果我沒記錯的話,在 2009 年前後,一位義大利的工程師 Antirez ,開源了 Redis。從此徹底顛覆了快取的市場,到現在大多數快取的業務都已用上 Redis,memcached 基本退出了歷史舞臺。Redis 最大的特點是擁有豐富的資料結構支援,不僅僅是簡單的 Key-Value,還包括佇列、集合、Sorted Set 等等,提供了非常豐富的表達力,而且 Redis 還提供 sub/pub 等超出資料庫範疇的便捷功能,使得幾乎一夜之間大家紛紛投入 Redis 的懷抱。

✦Twemproxy

但是隨著 Redis 漸漸的普及,而且越用越狠,另外記憶體也越來越便宜,人們開始尋求擴充套件單機 Redis 的方案,最早的嘗試是 twitter 開源的 twemproxy。twemproxy 是一個 Redis 中介軟體,基本只有最簡單的資料路由功能,並沒有動態的伸縮能力,但是還是受到了很多公司的追捧,因為確實沒其他替代方案。隨後的 Redis Cluster 也是難產了好久,時隔好幾年,中間出了 7 個 RC 版本,最後才釋出;2014 年底,我們開源了 Codis,解決了 Redis 中介軟體的資料彈性伸縮問題,目前廣泛應用於國內各大網際網路公司中,這個在網上也有很多文章介紹,我也就不展開了。所以在快取上面,開源社群現在倒是非常統一,就是 Redis 及其極其周邊的擴充套件方案。

✦MongoDB

在 NoSQL 的大家庭中,MongoDB 其實是一個異類,大多 NoSQL 捨棄掉 SQL 是為了追求更極致的效能和可擴充套件能力,而 MongoDB 主動選擇了文件作為對外的介面,非常像 JSON 的格式。Schema-less 的特性對於很多輕量級業務和快速變更的了網際網路業務意義很大,而且 MongoDB 的易用性很好,基本做到了開箱即用,開發者不需要費心研究資料的表結構,只需要往裡存就好了,這確實籠絡了一大批開發者。

儘管 MongoDB 早期的版本各種不穩定,效能也不太好(早期的 Mongo 並沒有儲存引擎,直接使用了 mmap 檔案),叢集模式還全是問題(比如至今還未解決的 Cluster 同步頻寬佔用過多的問題),但是因為確實太方便了,在早期的專案快速迭代中,Mongo 是一個不錯的選擇。但是這也正是它的問題,我不止一次聽到當專案變得龐大或者「嚴肅」的時候,團隊最後還是迴歸了關係型資料庫。Anyway,在 2014 年底 MongoDB 收購了 WiredTiger 後,在 2.8 版本中正式亮相,同時 3.0 版本後更是作為預設儲存引擎提供,效能和穩定性有了非常大的提升。

但是,從另一方面講,Schema-less 到底對軟體工程是好事還是壞事這個問題還是有待商榷。我個人是站在 Schema 這邊的,不過在一些小專案或者需要快速開發的專案中使用 Mongo 確實能提升很多的開發效率,這是毋庸置疑的。

✦HBase

說到 NoSQL 不得不提的是 HBase,HBase 作為 Hadoop 旗下的重要產品,Google Bigtable 的正統開源實現,是不是有一種欽定的感覺 :)。提到 HBase 就不得不提一下 Bigtable, Bigtable 是 Google 內部廣泛使用的分散式資料庫,介面也不是簡單的 Key-Value,按照論文的說法叫:multi-dimensional sorted map,也就是 Value 是按照列劃分的。Bigtable 構建在 GFS 之上,彌補了分散式檔案系統對於海量、小的、結構化資料的插入、更新以及、隨機讀請求的缺陷。

HBase 就是這麼一個系統的實現,底層依賴 HDFS。HBase 本身並不實際儲存資料,持久化的日誌和 SST file (HBase 也是 LSM-Tree 的結構) 直接儲存在 HDFS 上,Region Server (RS) 維護了 MemTable 以提供快速的查詢,寫入都是寫日誌,後臺進行 Compact,避免了直接隨機讀寫 HDFS。資料通過 Region 在邏輯上進行分割,負載均衡通過調節各個 Region Server 負責的 Region 區間實現。當某 Region 太大時,這個 Region 會分裂,後續可能由不同的 RS 負責,但是前面提到了,HBase 本身並不儲存資料,這裡的 Region 僅是邏輯上的,資料還是以檔案的形式儲存在 HDFS 上,所以 HBase 並不關心 Replication 、水平擴充套件和資料的分佈,統統交給 HDFS 解決。

和 Bigtable 一樣,HBase 提供行級的一致性,嚴格來說在 CAP 理論中它是一個 CP 的系統,但遺憾的是並沒有更進一步提供 ACID 的跨行事務。HBase 的好處就不用說了,顯而易見,通過擴充套件 RS 可以幾乎線性提升系統的吞吐,及 HDFS 本身就具有的水平擴充套件能力。

但是缺點仍然是有的。首先,Hadoop 的軟體棧是 Java,JVM 的 GC Tuning 是一個非常煩人的事情,即使已經調得很好了,平均延遲也得幾十毫秒;另外在架構設計上,HBase 本身並不儲存資料,所以可能造成客戶端請求的 RS 並不知道資料到底存在哪臺 HDFS DataNode 上,憑空多了一次 RPC;第三,HBase 和 Bigtable 一樣,並不支援跨行事務,在 Google 內部不停的有團隊基於 Bigtable 來做分散式事務的支援,比如 MegaStore、Percolator。後來 Jeff Dean 有次接受採訪也提到非常後悔沒有在 Bigtable 中加入跨行事務,不過還好這個遺憾在 Spanner 中得到了彌補,這個一會兒說。總體來說,HBase 還是一個非常健壯且久經考驗的系統,但是需要你有對於 Java 和 Hadoop 比較深入的瞭解後,才能玩轉,這也是 Hadoop 生態的一個問題,易用性真是不是太好,而且社群演進速度相對緩慢,也是因為歷史包袱過重的緣故吧。

✦Cassandra

提到 Cassandra (C*),雖然也是 Dynamo 的開源實現,但就沒有這種欽定的感覺了。C* 確實命途多舛,最早 2008 由 Facebook 開發並開源,早期的 C* 幾乎全是 bug,Facebook 後來索性也不再維護轉過頭搞 HBase 去了,一個爛攤子直接丟給社群。還好 DataStax 把這個專案撿起來商業化,搞了兩年,終於漸漸開始流行起來。

C* 不能簡單的歸納為讀快寫慢,或者讀慢寫快,因為採用了 qourm 的模型,調整複製的副本數以及讀的數量,可以達到不同的效果,對於一致性不是特別高的場景,可以選擇只從一個節點讀取資料,達到最高的讀效能。另外 C* 並不依賴分散式檔案系統,資料直接儲存在磁碟上,各個儲存節點之間自己維護複製關係,減少了一層 RPC 呼叫,延遲上對比 HBase 還是有一定優勢的。

不過即使使用 qourm 的模型也並不代表 C* 是一個強一致的系統。C* 並不幫你解決衝突,即使你 W(寫的副本數) + R(讀請求的副本數) > N(節點總數),C* 也沒辦法幫你決定哪些副本擁有更新的版本,因為每個資料的版本是一個 NTP 的時間戳或者客戶端自行提供,每臺機器可能都有誤差,所以有可能並不準確,這也就是為什麼 C* 是一個 AP 的系統。不過 C* 一個比較友好的地方是提供了 CQL,一個簡單的 SQL 方言,比起 HBase 在易用性上有明顯優勢。

即使作為一個 AP 系統,C* 已經挺快了,但是人們追求更高效能的腳步還是不會停止。應該是今年年初,ScyllaDB 的釋出就是典型的證明,ScyllaDB 是一個相容 C* 的 NoSQL 資料庫,不一樣的是,ScyllaDB 完全用 C++ 開發,同時使用了類似 DPDK 這樣的黑科技,具體我就不展開了,有興趣可以到 Scylla 的官網去看看。BTW, 國內的蘑菇街第一時間使用了 ScyllaDB,同時在 Scylla 的官網上 share 了他們的方案,效能還是很不錯的。

中介軟體與分庫分表 NoSQL 就先介紹到這裡,接下來我想說的是一些在基於單機關係型資料庫之上的中介軟體和分庫分表方案。

這些技術確實歷史悠久,而且也是沒有辦法的選擇。關係型資料庫不比 Redis,並不是簡單的寫一個類似 Twemproxy 的中介軟體就搞定了。資料庫的中介軟體需要考慮很多,比如解析 SQL,解析出 sharding key,然後根據 sharding key 分發請求,再合併;另外資料庫有事務,在中介軟體這層還需要維護 Session 及事務狀態,而且大多數方案並沒有辦法支援跨 shard 的事務。這就不可避免的導致了業務使用起來會比較麻煩,需要重寫程式碼,而且會增加邏輯的複雜度,更別提動態的擴容縮容和自動的故障恢復了。在叢集規模越來越大的情況下,運維和 DDL 的複雜度是指數級上升的。

✦中介軟體專案盤點

資料庫中介軟體最早的專案大概是 MySQL Proxy,用於實現讀寫分離。後來國人在這個領域有過很多著名專案,比如阿里的 Cobar 和 TDDL(並未完全開源);後來社群基於 Cobar 改進的 MyCAT、360 開源的 Atlas 等,都屬於這一類中介軟體產品;在中介軟體這個方案上基本走到頭的開源專案應該是 Youtube 的 Vitess。Vitess 基本上是一個集大成的中介軟體產品,內建了熱資料快取、水平動態分片、讀寫分離等等,但是代價也是整個專案非常複雜,另外文件也不太好。大概 1 年多以前,我們嘗試搭建起完整的 Vitess 叢集,但是並未成功,可見其複雜度。

另外一個值得一提的是 Postgres-XC 這個專案,Postgres-XC 的野心還是很大的,整體的架構有點像早期版本的 OceanBase,由一箇中央節點來處理協調分散式事務 / 解決衝突,資料分散在各個儲存節點上,應該是目前 PostgreSQL 社群最好的分散式擴充套件方案。其他的就不提了。

未來在哪裡?NewSQL! 一句話,NewSQL 就是未來。

2012 年 Google 在 OSDI 上發表了 Spanner 的論文,2013 年在 SIGMOD 發表了 F1 的論文。這兩篇論文讓業界第一次看到了關係模型和 NoSQL 的擴充套件性在超龐大叢集規模上融合的可能性。在此之前,大家普遍認為這個是不可能的,即使是 Google 也經歷了 Megastore 這樣的失敗。

✦Spanner 綜述

但是 Spanner 的創新之處在於通過硬體(GPS 時鐘 + 原子鐘)來解決時鐘同步的問題。在分散式系統裡,時鐘是最讓人頭痛的問題,剛才提到了 C* 為什麼不是一個強 C 的系統,正是因為時鐘的問題。而 Spanner 的厲害之處在於即使兩個資料中心隔得非常遠,不需要有通訊(因為通訊的代價太大,最快也就是光速)就能保證 TrueTime API 的時鐘誤差在一個很小的範圍內(10ms)。另外 Spanner 沿用了很多 Bigtable 的設計,比如 Tablet / Directory 等,同時在 Replica 這層使用 Paxos 複製,並未完全依賴底層的分散式檔案系統。但是 Spanner 的設計底層仍然沿用了 Colossus,不過論文裡也說是可以未來改進的點。

Google 的內部的資料庫儲存業務,大多是 3~5 副本,重要一點的 7 副本,遍佈全球各大洲的資料中心,由於普遍使用了 Paxos,延遲是可以縮短到一個可以接受的範圍(Google 的風格一向是追求吞吐的水平擴充套件而不是低延遲,從悲觀鎖的選擇也能看得出來,因為跨資料中心複製是必選的,延遲不可能低,對於低延遲的場景,業務層自己解決或者依賴快取)。另外由 Paxos 帶來的 Auto-Failover 能力,更是能讓整個叢集即使資料中心癱瘓,業務層都是透明無感知的。另外 F1 構建在 Spanner 之上,對外提供了更豐富的 SQL 語法支援,F1 更像一個分散式 MPP SQL——F1 本身並不儲存資料,而是將客戶端的 SQL 翻譯成類似 MapReduce 的任務,呼叫 Spanner 來完成請求。

其實 Spanner 和 F1 除了 TrueTime 整個系統並沒有用什麼全新的演算法,其意義在於這是近些年來第一個 NewSQL 在生產環境中提供服務的分散式系統技術。

Spanner 和 F1 有以下幾個重點:

  1. 完整的 SQL 支援,ACID 事務;
  2. 彈性伸縮能力;
  3. 自動的故障轉移和故障恢復,多機房異地災備。

NewSQL 特性確實非常誘人,在 Google 內部,大量的業務已經從原來的 Bigtable 切換到 Spanner 之上。我相信未來幾年,整個業界的趨勢也是如此,就像當年的 Hadoop 一樣,Google 的基礎軟體的技術趨勢是走在社群前面的。

✦社群反應

Spanner 的論文發表之後,當然也有社群的追隨者開始實現(比如我們 :D ),第一個團隊是在紐約的 CockroachDB。CockroachDB 的團隊的組成還是非常豪華的,早期團隊由是 Google 的分散式檔案系統 Colossus 團隊的成員組成;技術上來說,Cockroach 的設計和 Spanner 很像,不一樣的地方是沒有選擇 TrueTime 而是 HLC (Hybrid logical clock),也就是 NTP + 邏輯時鐘來代替 TrueTime 時間戳;另外 Cockroach 選用了 Raft 代替 Paxos 實現複製和自動容災,底層儲存依賴 RocksDB 實現,整個專案使用 Go 語言開發,對外介面選用 PostgreSQL 的 SQL 子集。

✦TiDB

目前從全球範圍來看,另一個朝著 Spanner / F1 的開源實現這個目標上走的產品是 TiDB(終於談到我們的產品了)。TiDB 本質上是一個更加正統的 Spanner 和 F1 實現,並不像 CockroachDB 那樣選擇將 SQL 和 Key-Value 融合,而是像 Spanner 和 F1 一樣選擇分離,這樣分層的思想也是貫穿整個 TiDB 專案始終的。對於測試、滾動升級以及各層的複雜度控制會比較有優勢;另外 TiDB 選擇了 MySQL 協議和語法的相容,MySQL 社群的 ORM 框架和運維工具,直接可以應用在 TiDB 上。

和 F1 一樣,TiDB 是一個無狀態的 MPP SQL Layer,整個系統的底層是依賴 TiKV 來提供分散式儲存和分散式事務的支援。TiKV 的分散式事務模型採用的是 Google Percolator 的模型,但是在此之上做了很多優化。Percolator 的優點是去中心化程度非常高,整個叢集不需要一個獨立的事務管理模組,事務提交狀態這些資訊其實是均勻分散在系統的各個 Key 的 meta 中,整個模型唯一依賴的是一個授時伺服器。在我們的系統上,極限情況這個授時伺服器每秒能分配 400w 以上個單調遞增的時間戳,大多數情況基本夠用了(畢竟有 Google 量級的場景並不多見);同時在 TiKV 中,這個授時服務本身是高可用的,也不存在單點故障的問題。

TiKV 和 CockroachDB 一樣也是選擇了 Raft 作為整個資料庫的基礎;不一樣的是,TiKV 整體採用 Rust 語言開發,作為一個沒有 GC 和 Runtime 的語言,在效能上可以挖掘的潛力會更大。

✦關於未來

我覺得未來的資料庫會有幾個趨勢,也是 TiDB 專案追求的目標:

●資料庫會隨著業務雲化,未來一切的業務都會跑在雲端,不管是私有云、公有云還是混合雲,運維團隊接觸的可能再也不是真實的物理機,而是一個個隔離的容器或者「計算資源」。這對資料庫也是一個挑戰,因為資料庫天生就是有狀態的,資料總是要儲存在物理的磁碟上,而移動資料的代價比移動容器的代價可能大很多。

●多租戶技術會成為標配,一個大資料庫承載一切的業務,資料在底層打通,上層通過許可權,容器等技術進行隔離;但是資料的打通和擴充套件會變得異常簡單,結合第一點提到的雲化,業務層可以再也不用關心物理機的容量和拓撲,只需要認為底層是一個無窮大的資料庫平臺即可,不用再擔心單機容量和負載均衡等問題。

●OLAP 和 OLTP 會進一步細分,底層儲存也許會共享一套,但是 SQL 優化器這層的實現一定是千差萬別的。對於使用者而言,如果能使用同一套標準的語法和規則來進行資料的讀寫和分析,會有更好的體驗。

●在未來分散式資料庫系統上,主從日誌同步這樣落後的備份方式會被 Multi-Paxos / Raft 這樣更強的分散式一致性演算法替代,人工的資料庫運維在管理大規模資料庫叢集時是不可能的,所有的故障恢復和高可用都會是高度自動化的。

Q & A 問:HANA 等記憶體資料庫怎麼保證系統掉電而處理結果不丟?傳統資料庫也用快取,可是 HANA 用的記憶體太大。

黃東旭:沒用過 HANA,但是直觀感覺這類記憶體資料庫的可用性可能通過集中方式保證: ●寫入會先寫 WAL; > - 寫入可能會通過主從或者 paxos 之類的演算法做同步和冗餘複製還有 HANA 本身就是記憶體資料庫,會盡可能把資料放到記憶體裡,這樣查詢才能快呀。

問:對於傳統創業公司如何彌補 NoSQL 的技術短板?快速的引入 NoSQL 提高效率?

黃東旭:選用 NoSQL 主要注意兩點:

  1. 做好業務的調研,估計併發量,資料量,資料的結構看看適不適合;
  2. 對各種 NoSQL 擅長和不擅長的地方都儘可能瞭解。 不要盲目相信關係型資料庫,也不要盲目相信 NoSQL,沒有銀彈的。

問:有多個條件 比如年齡 20 到 30 或年齡 35 到 40 並且加入購物車或下單 這種資料怎麼儲存?

黃東旭:購物車這種場景是典型的 OLTP 的場景,可以選用關係型資料庫 MySQL PostgreSQL 什麼的,如果對於擴充套件性的資料跨機房有要求的話,可以調研一下 NewSQL,比如我們的 TiDB。

問:多緯度查詢應該選擇哪種資料庫?

黃東旭:多緯度查詢可以說是一個 OLAP 的場景,可以選用 Greenplum 或者 Vertica 之類的分析性資料庫。

問:想知道為什麼需要這些開源的資料庫,既然已經有了 MySQL、DB2、Oracle 這些成熟的資料庫,成本考慮,還是傳統資料庫滿足不了需求?

黃東旭:對,傳統資料庫的擴充套件性是有問題的,在海量併發和資料量的場景下很難支援業務。所以可以看到比較大的網際網路公司基本都有自己的分散式資料庫方案。

問:未來可能不再需要資料倉儲嗎?

黃東旭:大家可以想想資料倉儲的定義,如果是還需要離線的從線上庫倒騰資料到資料倉儲上,這樣很難做到實時查詢,而且空間的利用率也低,我認為是目前並沒有太好的方案的情況下的折衷…… 如果有一個更好的資料庫能解決資料倉儲的場景,為什麼還需要一個獨立的資料倉儲?

原文連結

更多原創文章乾貨分享,請關注公眾號
  • 開源資料庫的現狀
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章