hbase表結構設計研究
因為一直在做hbase的應用層面的開發,所以體會的比較深的一點是hbase的表結構設計會對系統的效能以及開銷上造成很大的區別,本篇文章先按照hbase表中的rowkey、columnfamily、column、timestamp幾個方面進行一些分析。最後結合分析如何設計一種適合應用的高效表結構。
1、表的屬性
(1)最大版本數:通常是3,如果對於更新比較頻繁的應用完全可以設定為1,能夠快速的淘汰無用資料,對於節省儲存空間和提高查詢速度有效果。不過這類需求在海量資料領域比較小眾。
(2)壓縮演算法:可以嘗試一下最新出爐的snappy演算法,相對lzo來說,壓縮率接近,壓縮效率稍高,解壓效率高很多。
(3)inmemory:表在記憶體中存放,一直會被忽略的屬性。如果完全將資料存放在記憶體中,那麼hbase和現在流行的記憶體資料庫memorycached和redis效能差距有多少,尚待實測。
(4)bloomfilter:根據應用來定,看需要精確到rowkey還是column。不過這裡需要理解一下原理,bloomfilter的作用是對一個region下查詢記錄所在的hfile有用。即如果一個region下的hfile數量很多,bloomfilter的作用越明顯。適合那種compaction趕不上flush速度的應用。
2、rowkey
rowkey是hbase的key-value儲存中的key,通常使用使用者要查詢的欄位作為rowkey,查詢結果作為value。可以通過設計滿足幾種不同的查詢需求。
(1)數字rowkey的從大到小排序:原生hbase只支援從小到大的排序,這樣就對於排行榜一類的查詢需求很尷尬。那麼採用rowkey = Integer.MAX_VALUE-rowkey的方式將rowkey進行轉換,最大的變最小,最小的變最大。在應用層再轉回來即可完成排序需求。
(2)rowkey的雜湊原則:如果rowkey是類似時間戳的方式遞增的生成,建議不要使用正序直接寫入rowkey,而是採用reverse的方式反轉rowkey,使得rowkey大致均衡分佈,這樣設計有個好處是能將regionserver的負載均衡,否則容易產生所有新資料都在一個regionserver上堆積的現象,這一點還可以結合table的預切分一起設計。
3、columnfamily
columnfamily儘量少,原因是過多的columnfamily之間會互相影響。
4、column
對於column需要擴充套件的應用,column可以按普通的方式設計,但是對於列相對固定的應用,最好採用將一行記錄封裝到一個column中的方式,這樣能夠節省儲存空間。封裝的方式推薦protocolbuffer。
以下會分場景介紹一些特殊的表結構設計方法,只是一些摸索,歡迎討論:
value數目過多場景下的表結構設計:
目前我碰到了一種key-value的資料結構,某一個key下面包含的column很多,以致於客戶端查詢的時候oom,bulkload寫入的時候oom,regionsplit的時候失敗這三種後果。通常來講,hbase的column數目不要超過百萬這個數量級。在官方的說明和我實際的測試中都驗證了這一點。
有兩種思路可以參考,第一種是單獨處理這些特殊的rowkey,第二種如下:
可以考慮將column設計到rowkey的方法解決。例如原來的rowkey是uid1,,column是uid2,uid3...。重新設計之後rowkey為<uid1>~<uid2>,<uid1>~<uid3>...當然大家會有疑問,這種方式如何查詢,如果要查詢uid1下面的所有uid怎麼辦。這裡說明一下hbase並不是只有get一種隨機讀取的方法。而是含有scan(startkey,endkey)的掃描方法,而這種方法和get的效率相當。需要取得uid1下的記錄只需要new Scan("uid1~","uid1~~")即可。
這裡的設計靈感來自於hadoop world大會上的一篇文章,這篇文章本身也很棒,推薦大家看一下http://www.cloudera.com/resource/hadoop-world-2011-presentation-slides-advanced-hbase-schema-design/