深入淺出hbase和bigtable

關於hbase的實現,基本遵循bigtable的論文,而這篇論文的核心就是:

  1. 一個分散式的kv存儲,如何設計key value,可以讓模型更具有業務實用性
  2. 分散式一致性設計範式:在分散式系統中,哪些組件可以是無狀態的
  3. 分散式系統工程實踐的範式:三副本的情況下如何降低rt(response time)

1. 如何理解sorted map和column family

bigtable論文的精髓點就在於分散式的有序map,一切設計也是圍繞這個結構:

A Bigtable is a sparse, distributed, persistent multidimensional

sorted map. The map is indexed by a row

key, column key, and a timestamp; each value in the map

is an uninterpreted array of bytes.

結構寫出來是這樣:

(row:string, column:string, time:int64) -> string

難點:column family如何理解:

相同的column family 不同的column key的數據會被物理上存儲在一起,方便進行一起range scan。column family 有一點類似於rdbms中的multi-column index,如果沒有column family,那麼bigtable的存儲模型就是完全的kv range型的,而有了column family,則可以豐富查詢方式,加快同一個column family下的range scan,是一種物理上將一行中某幾個部分數據順序存儲在磁碟的聲明,類似於spanner中的parent-child table relation。

難點2:業務中如何設計rowkey和column family,這個在下面詳細討論。

hbase的實際存儲,同一個column family的會被存儲到同一個Hfile

另一個理解column family的圖,可以看出同時取column1,column2的查詢,可以完全不去動用column y的hfile文件

2. hbase中的組件

從一次put請求涉及的組件來熟悉hbase的不同組件,其中

hbase region server = bigtable tablet

hdfs, hlog, dfs client = gfs 中的相應概念

每個region server主要處理一段key range的請求,而哪些key range需要路由到什麼region server的信息保存在其中一個region server上,這麼說可能有一點繞,來看一個實際的寫入例子。

如圖,client發起一次put請求後,涉及到的主要調用,同步的包括:

  1. 通過zk獲得region server地址
  2. region server 把一個row put,變成多句 kv put
  3. 先寫入HLog,作為WAL log
  4. 寫入MemStore
  5. 返回

其中通過zk獲得region server地址的行為又可以精細化為:

  1. 從zk中獲取meta table的region server
  2. 讀取meta table的region server獲取rowkey的真實region server

通過zk獲取region server地址並寫入,可能涉及兩個region server

在同步調用中,不同的column family的寫入都在同一個Hlog,也對應著同一個DataNode,所以單行的更新,涉及多個column family,即使最終這些數據會分別寫入到不同column family對應的Hfile中,仍然是可以保證atomic和duration,isolation和visibility沒有保證,所以嚴格說不能算單行「事務」,但如果從事務要麼一起成功,要麼一起失敗這種狹隘定義來看,也可以算單行「事務」。

3. 如何設計rowkey和column family

首先,應該考慮到rowkey設計中不同於關係型資料庫的表結構的幾個反直覺點:

  1. 查詢必須要帶rowkey,至少也需要拼出rowkey範圍,否則效率極低
  2. rowkey由用戶自行定義且用戶自行保證rowkey唯一性

雖然很多的大型業務團隊也使用一套自己的seq id generator,但大部分的小型業務都是直接依賴資料庫提供的單調遞增id,沒有自行保證seq id唯一性且把有意義的業務欄位放入到seq id加速查詢和保證分散式全局唯一的經驗。

在這裡,可以參考OPENTSDB的設計經驗,它的rowkey為 [metric_type][event_timestamp],這個rowkey非常適合指定metric_type下的timestamp range查詢。(這個rowkey可能也不是完美的,這個設計下的寫入會集中在同一個region server,導致寫入熱點,達不到分攤寫入流量的目的,但是,假如沒用timestamp做後綴結尾,而是假如一個後綴結尾隨機數來把寫流量分攤到更多的region server,又會影響讀取效率,請自行判斷trade off)

整理clumn family的設計原則:

  1. 沒想好如何拆分的時候,就只用一個column family
  2. 把需要一起被取出的所有列放在同一個column family中
  3. 當range scan的時候,確定不需要獲取的列放在另一個column family

4. REF

big table 論文:static.googleusercontent.com

hbase 的schema desgin建議:0b4af6cdc2f0c5998459-c0245c5c937c5dedcca3f1764ecc9b2f.r43.cf2.rackcdn.com

hbase datamodel:Apache HBase ? Reference Guide


推薦閱讀:

什麼鬼!基於備份恢復的數據還能變多?
Python採集微博熱評進行情感分析祝你狗年脫單
七周成為數據分析師:SQL,從熟練到掌握
sql中插入中文問題

TAG:分散式計算 | 資料庫 | 計算機科學 |