BigTable 有什麼值得稱道(牛)的地方?

BigTable 是 Google 在許多產品中使用的一種分散式結構化數據存儲系統,被設計用來處理海量數據。


Bigtable 論文已經十年了。論文的第一大貢獻是編程模型方面,當時大家都還在摸索在這種大 PC 機群環境下存儲系統應該提供怎樣的編程模型,要簡單易理解,滿足產品開發需求,又要在實現上能水平擴展支持海量存儲。Bigtable 的「排序大表 + Column Family」在當時就不是什麼新東西,但被證明了是一個非常成功的設計,能概括從線上到線下很多的業務需求,並且有很好的靈活性和擴展性。到今天 Bigtable 還有極廣泛的應用,之後 MegaStore(公開版本是 AppEngine 上的 DataStore) 直接基於 Bigtable 構建,再後來的 Spanner 在單 tablet 上的存儲乾脆復用了 Bigtable 的版本。

在當時,人們對這種大規模分散式系統環境的認識還並不系統,談得最多的是 CAP —— CAP 不可兼得是一個定律,但它沒有告訴你應該怎麼根據業務特點取捨。當時另一個有趣的項目是 Amazon 的 Dynamo, 它基於不同的取捨方向,追求 A 和 P(Bigtable 的 A 並不是特別好),讓程序員自己動手解決寫衝突問題。從今天看,就不及 Bigtable 的模型成功。(私貨:我一直不看好 Cassandra)

在實現上,Bigtable 的另一點貢獻是把 LSM (Log-Structured Merge) Tree 這種古老的技術帶回前台。它和當時全部機械硬碟的現狀以及 GFS 的編程模型極搭。把隨機寫全部轉化為順序寫,實現了非常好的吞吐和即使對線上應用也可以接受的延遲(有坑,論文里就隱藏了坑),只讀 SSTable dump 極大簡化了設計。用 GFS 解決底層存儲備份一系列問題,也大大簡化了 Bigtable 自身的實現。SSTable + LSM Tree 這一部分的成果開源在了 LevelDB, 有廣泛的應用,也啟發了其他的很多開源項目。

Jeff Dean 自己對 Bigtable 最不滿意的是沒有提供跨行事務支持。這個故事很有趣:跨行事務天生是不可擴展,你沒它辦法,Bigtable 一開始並沒有提供跨行事務就是這個原因。但是,它不可擴展是個實現問題,業務就是需要啊,你不提供官方實現,業務就會在上層企圖自己搞事務,不出所料絕大部分分散式事務實現都是錯的。Jeff Dean 後來實在看不過去在 Spanner 提供了官方分散式事務支持。

Bigtable 論文出來後不久,國內應該不止一個團隊在企圖複製它。當時 Bigtable 論文給我的感受倒不是它有多大創新,而是它在有機群管理軟體(當時還不知道它叫 borg)有 GFS 有 Chubby 做基礎,實現起來並不困難(論文里說了大概就10萬行C++),有了 Bigtable 的基礎,Google 實現其他的東西可以更快更得心應手。這是拿機群當操作系統做的思路,這種打法,你想要跟著打,會追得很辛苦,你想要走捷徑取得局部成果,又必然後勁不足。稍微有點毀三觀,這麼多年之後我不用翻原文都能記起 Bigtable 等老三篇的細節,就是那時被碾壓的印記。

我09年底的時候在珠三角技術沙龍有個分享 http://www.slideshare.net/kyhpudding/dreaming-infrastructure 記錄了當時我對這類分散式存儲系統的總結和思考,很多觀點今天看來依然適用。


lsm tree的應用,tablet的meta表和root表兩級索引設計,按列存儲對查詢和壓縮的優化,這幾項對後面分散式kv或資料庫系統設計的影響很大

不足之處是與GFS的兩級級結構,看起來優雅,實際上對可用性和性能的犧牲非常大,且比較難實現完整的多機房副本,也很難支持讀取副本


0:強一致性

這個是大前提,很多分散式資料庫是AP的,沒有強一致性,比如Cassandra。對用戶來說,一旦需要強一致性,那麼AP類的都不能考慮;反過來即使不需要強一致性,用CP的儘可能搞高可用性也是能用的。對一個公司來說,如果部分業務需要強一致性,部分業務不需要,只搭一個系統的話,自然要上CP的系統。當然對於HBase和Cassandra來說,用戶規模也和市場推廣什麼的有關係了,和技術無關就不在這談了。

1:設計簡單

基於分散式文件系統,把資料庫和底層存儲分開,這樣可以讓兩個系統分別都比較容易寫(當然,對應的開源的HDFS/HBase的代碼質量肯定趕不上BigTable和GFS了)。壞處是任何一個tablet/region都只在一個機器上,一旦這個機器掛了需要讓其他機器讀log恢復,造成可用性問題。現在一些比較新的分散式CP資料庫,很多用paxos/raft+rocksdb之類的模式,好處是leader掛了重新在group里選一個就能用,恢復時間短很多;壞處是三備份也要三個完整的LSM,內存和CPU的消耗也是三倍。BigTable不清楚後續有沒有改進這個問題,HBase的解決方案是搞slave region,找另外一個RS非同步的從WAL里讀數據放內存里,平時可以作為最終一致性的讀寫分離用,RS掛的時候也可以直接從slave region所在的server上補上少量delay的log後直接服務,恢復時間也很短,用二倍的內存和不到二倍的CPU做了類似的事情。

2:row key有序

因為有中心節點比較方便做split/move的操作,可以在讓row key有序的前提下儘可能讓集群balance。可以按順序讀對用戶是非常友好的,而按哈希搞的NoSQL在用的時候總是容易遇到各種不爽。

3:在數據模型層面支持多版本

技術上多版本/mvcc啥的是普遍都有的,但把多版本這個東西暴露在數據模型,對很多業務也是非常方便的。


當年和彼岸一起翻譯Big Table的論文的時候,就注意到幾個特點,一個是按行組織的子表是分散式存儲,便於冗餘容錯,分散式查詢。一個是value用字元串格式,應用層負責解釋,靈活,便於查錯。第三是針對稀疏表格(normalization的結果)和典型重複內容進行快速壓縮,以CPU帶寬換硬碟帶寬,是一筆賠率幾十兆的好買賣。第四是條件表達式簡單,這個見仁見智。

不過big table也顯示出其不適應快速響應查詢的特點。現在google有big query,是按照列來組織的,查詢速度更快(接近實時的查詢Tera byte級別數據),可以快速返回近似查詢結果,也是很有意思的。


需要明確的一點是bigtable實現的數據模型很"簡單",大家可以去看看bigtable論文,這點和傳統關係型資料庫很不一樣,此類模型的數據也更容易擴展.它是為了海量數據而生,不是海量數據也體現不了它的優勢.

bigtable牛的地方是:

1. 解決了海量數據的可用性和伸縮性,因海量數據面對的各種網路,硬體,服務的問題太多了,bigtable也經過幾年的不斷調整和優化才趨於完善;

2. 和GFS配合的天衣無縫,極大的優化了寫入性能;

3. 優秀的壓縮方案.


除了其他回答中提到的,BigTable的並發創建Secondary Indexes的性能十分強大,即使一個Entity有上千個Secondary Indexes,也能瞬間創建完畢。

另外BigTable支持整個Entity(Row) Group級別的事務(Transaction),或者說支持若干連續存放的Entities的鎖定。而HBase不支持Row Group,所以只能支持單Row的鎖定。

最新的BigTable版本已經可以支持跨Entity Groups的事務。


今天剛看完,自己寫幾點看法。

1. 對於一致性的處理,BigTable將SSTable不可改變化,然後對memtable使用copy-on-write技術實現讀寫並行。

2. MetaTablet中的row key是通過table id和end row來計算出的。因為這裡是有序的,所以在讀取row/column型的數據時可以利用到有序性

3. 另外關於SSTable的一些操作個人認為也是很巧妙,特別是關於delete data的處理。

4. Locality Groups的使用,不過貌似在hbase中沒有這個概念,直接處理成一個column family是一個locality group了

暫時想到這麼多,以後有新想法再補充。


在列擴展上有優勢,比較適合飛快發展的業務。對於實時性要求及數據一致性要求較高的業務不適合。


更適合存儲以XML進行描述的數據,如RDF或者是OWL


推薦閱讀:

樂觀鎖為什麼適用於衝突少的場景,以及應用在內存資料庫中?
Google Spanner 是一個什麼樣東西?對未來會產生什麼樣的影響?
有沒有公司在用access建資料庫?
有哪些靠譜的注入攻擊的掃描工具?
「用戶標籤」在資料庫設計時應該如何存儲?

TAG:雲計算 | 資料庫 | Bigtable | 谷歌Google | 分散式系統 |