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