一種HBase的表region切分和rowkey設計方案
場景
HBase的region隨著大小的不斷變大會觸發一個閾值,默認為256M,一旦觸發那麼他就會自動的分裂開來,隨著region變多hbase管理起來也越發困難,性能也會明顯下降。當然更多的region使得高並發成為可能。一種較好的實踐方案就是一方面預切分HBase的region,確定region的個數,保證並發性能,另一方面設置較高的region size分裂閾值,保證region數量不變。
方案
預切分方法:
./bin/hbase org.apache.hadoop.hbase.util.RegionSplitter -c 500 test -f t1:t2:t3
上面的命令行工具給以為你切分一個500region的test表,分別包含了三個列族:t1,t2,t3。
然後在hbase-site.xml設置hbase.hregion.max.filesize為104857600(=1024*1024*100=100G),設置為100G,這樣很長一段時間內不會出現region分裂。建議一個節點分到1000region,可以滿足並發,而且不至於讓master壓力過大。
rowkey設計方案:
需要指出的是這種預切分方法用了一種默認演算法md5stringsplit來分配region的startkey,endkey。這種得到的是一個8位的右移一位的md5的字元串。實際上就是md5前八位然後右移。這樣在設計rowkey的時候就要千萬注意了!因為這樣分配出來的region是00000000~7fffffff。所以為了讓rowkey能夠均勻落入到這個範圍需要md5(id)>>1 + id。提示一下:如果你使用的md5(id)+id的方法設計了rowkey,入庫時如果數據量很大則會導致hot region。rs就會頻繁的掛掉了,因為大部分數據都落入最後一個region了。
rowkey生成的具體的java代碼如下:
private String makeRowKey(String id){ String md5_content = null; try { MessageDigest messageDigest = MessageDigest.getInstance("MD5"); messageDigest.reset(); messageDigest.update(id.getBytes()); byte[] bytes = messageDigest.digest(); md5_content = new String(Hex.encodeHex(bytes)); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } //turn right md5 String right_md5_id = Integer.toHexString(Integer.parseInt(md5_content.substring(0,7),16)>>1); while(right_md5_id.length()<7){ right_md5_id = "0" + right_md5_id; } return right_md5_id + "::" + id; }
這樣做的好處就是在寫入數據時可以使rowkey均勻的寫入,當然讀取的時候還需要拿著id變成md5再去讀取,批量讀取與時間戳前置方法相比肯定沒有任何優勢了。不過隨機讀取也會使rs的負載均衡。
上面的這種設計適合絕大多數場景。可以作為一個良好的實踐。
關注分散式存儲技術以及分散式計算方法
推薦閱讀:
※region HFile DataNode 三者的區別與關係?
※怎麼看hadoop的源碼,求大神指教?
※從頭學習大數據培訓課程 NOSQL 資料庫 hbase(一)Hbase 概述與安裝、Hbase 原理和簡單的 shell 操作
※饒軍:Apache Kafka的過去,現在,和未來
※SOFARPC 集成 ZooKeeper 註冊中心
TAG:HBase |