前言
newbie剛接觸HBase,遇到幾個初學者常見的關於HBase問題,這裏就問題就不多做介紹,主要還是編碼優化問題,下面專門介紹以下幾點,希望對於初學者有所幫助。
基於HBase-0.94.x 版本
Tips
RowKey的設計
HBase的無論什麼操作都是對rowkey進行掃描操作的,rowkey的排序是按照字典序來排的。
IO考慮
爲讀優化
設計行健時,儘量把行健按照序號緊挨一起,減少掃描。
爲寫優化
主要是考慮所有的rowkey不要寫到同一個region上,這樣會導致其他機器很空閒,只有這個region的吞吐量就是你應用的吞吐量
例如時間戳做行健就會出現這個問題。
解決方法主要是兩個:
- 散列,建表時分表,然後寫入時使用散列函數,將行健打散分佈,這樣做只是爲了寫操作多的優化,對於讀來說,可能是災難(全表掃描)
- salting,使用隨機值做前綴,解決散列全表掃描的問題
Merge相同的rowKey
因爲HBase對於每一個命令(put,delete,get,increment)都是起一個線程來做的,每個命令基本都有
addFamily(), addCloumns()方法可以使用
這裏漏掉一點是爲什麼要merge:因爲HBase對於每一個命令都是起一個thread來執行(0.94),所以爲了減少thread的創建,所以儘量merge
這裏有人會問,merge之後的執行性能和merge之前的性能如何,會快還是慢??其實性能相差無幾,具體可以去淘寶量子恆道blog(貌似打不開)上去看看測試結果
是否需要自己做HTable Connection緩存管理
這一點是不需要的,HBase本身有Cache機制的,主要在HConnectionManager裏面做管理,它會做緩存。每次close時也會檢查該cacheINstance是否還有reference,如果有就暫時不close,沒有就close,reference-1。詳細請看HConnectionManager源碼;
public static HConnection getConnection(final Configuration conf)
throws IOException {
HConnectionKey connectionKey = new HConnectionKey(conf);
synchronized (CONNECTION_INSTANCES) {
HConnectionImplementation connection = CONNECTION_INSTANCES.get(connectionKey);
if (connection == null) {
connection = (HConnectionImplementation)createConnection(conf, true);
CONNECTION_INSTANCES.put(connectionKey, connection);
} else if (connection.isClosed()) {
HConnectionManager.deleteConnection(connectionKey, true);
connection = (HConnectionImplementation)createConnection(conf, true);
CONNECTION_INSTANCES.put(connectionKey, connection);
}
connection.incCount();
return connection;
}
}
Code
我自己實現了一個簡單的Hbase Client,不是線程安全,在github上,可以clone下參考,僅供參考(爲經測試,可能存在錯誤)
simple-hbase-client: git clone https://github.com/zhgwen/simple-hbase-client.git