1. 程式人生 > >HBase rowkey設計-熱點問題

HBase rowkey設計-熱點問題

        當處理由連續事件得到的資料時,即時間上連續的資料。這些資料可能來自於某個感測器網路、證券交易或者一個監控系統。它們顯著的特點就是rowkey中含有事件發生時間。帶來的一個問題便是HBase對於row的不均衡分佈,它們被儲存在一個唯一的rowkey區間中,被稱為region,區間的範圍被稱為Start Key和End Key。
        如果將單調遞增的時間型別資料作為rowkey,value很容易被雜湊到同一個Region中,這樣它們會被儲存在同一個伺服器上,從而所有的訪問和更新操作都會集中到這一臺伺服器上,從而在叢集中形成一個hot spot,從而不能將叢集的整體效能發揮出來。

        要解決這個問題是非常容易的,只需要將所有的資料雜湊到全部的Region上即可。這是可以做到的,在rowkey前面加上一個非線性字首,或者翻轉rowkey,或者將rowkey hash化。

        資料分散到不同的Region上儲存,可以利用HBase的並行特點,可以利用MapReduce和spark計算框架並行處理資料。

下列程式碼是參考(在rowkey前面加上一個非線性字首)

  1. import java.io.IOException;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. import org.apache.hadoop.conf.Configuration;  
  5. import org.apache.hadoop.hbase.HBaseConfiguration;  
  6. import org.apache.hadoop.hbase.HColumnDescriptor;  
  7. import org.apache.hadoop.hbase.HTableDescriptor;  
  8. import org.apache.hadoop.hbase.KeyValue;  
  9. import org.apache.hadoop.hbase.MasterNotRunningException;  
  10. import org.apache.hadoop.hbase.TableName;  
  11. import org.apache.hadoop.hbase.ZooKeeperConnectionException;  
  12. import org.apache.hadoop.hbase.client.Get;  
  13. import org.apache.hadoop.hbase.client.HBaseAdmin;  
  14. import org.apache.hadoop.hbase.client.HTable;  
  15. import org.apache.hadoop.hbase.client.HTablePool;  
  16. import org.apache.hadoop.hbase.client.Put;  
  17. import org.apache.hadoop.hbase.client.Result;  
  18. import org.apache.hadoop.hbase.client.ResultScanner;  
  19. import org.apache.hadoop.hbase.client.Scan;  
  20. import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;  
  21. import org.apache.hadoop.hbase.filter.Filter;  
  22. import org.apache.hadoop.hbase.filter.FilterList;  
  23. import org.apache.hadoop.hbase.filter.PrefixFilter;  
  24. import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;  
  25. import org.apache.hadoop.hbase.util.Bytes;  
  26. import org.slf4j.Logger;  
  27. import org.slf4j.LoggerFactory;  
  28. import com.kktest.hbase.HashChoreWoker;  
  29. import com.kktest.hbase.HashRowKeyGenerator;  
  30. import com.kktest.hbase.RowKeyGenerator;  
  31. import com.kktest.hbase.BitUtils;  
  32. /** 
  33.  * hbase 客戶端 
  34.  *  
  35.  * @author kuang hj 
  36.  *  
  37.  */
  38. @SuppressWarnings("all")  
  39. publicclass HBaseClient {  
  40.     privatestatic Logger logger = LoggerFactory.getLogger(HBaseClient.class);  
  41.     privatestatic Configuration config;  
  42.     static {  
  43.         config = HBaseConfiguration.create();  
  44.         config.set("hbase.zookeeper.quorum",  
  45.                 "192.168.1.100:2181,192.168.1.101:2181,192.168.1.103:2181");  
  46.     }  
  47.     /** 
  48.      * 根據隨機雜湊(hash)建立分割槽表 
  49.      *  
  50.      * @throws Exception 
  51.      *             hash_split_table 
  52.      */
  53.     publicstaticvoid testHashAndCreateTable(String tableNameTmp,  
  54.             String columnFamily) throws Exception {        // 取隨機雜湊 10 代表 10個分割槽
  55.         HashChoreWoker worker = new HashChoreWoker(100000010);  
  56.         byte[][] splitKeys = worker.calcSplitKeys();  
  57.         HBaseAdmin admin = new HBaseAdmin(config);  
  58.         TableName tableName = TableName.valueOf(tableNameTmp);  
  59.         if (admin.tableExists(tableName)) {  
  60.             try {  
  61.                 admin.disableTable(tableName);  
  62.             } catch (Exception e) {  
  63.             }  
  64.             admin.deleteTable(tableName);  
  65.         }  
  66.         HTableDescriptor tableDesc = new HTableDescriptor(tableName);  
  67.         HColumnDescriptor columnDesc = new HColumnDescriptor(  
  68.                 Bytes.toBytes(columnFamily));  
  69.         columnDesc.setMaxVersions(1);  
  70.         tableDesc.addFamily(columnDesc);  
  71.         admin.createTable(tableDesc, splitKeys);  
  72.         admin.close();  
  73.     }  
  74.     /** 
  75.      * @Title: queryData 
  76.      * @Description: 從HBase查詢出資料 
  77.      * @author kuang hj 
  78.      * @param tableName 
  79.      *            表名 
  80.      * @param rowkey 
  81.      *            rowkey 
  82.      * @return 返回使用者資訊的list 
  83.      * @throws Exception 
  84.      */
  85.     @SuppressWarnings("all")  
  86.     publicstatic ArrayList<String> queryData(String tableName, String rowkey)  
  87.             throws Exception {  
  88.         ArrayList<String> list = new ArrayList<String>();  
  89.         logger.info("開始時間");  
  90.         //在高併發的情況下,最好不要使用HTable/HTablePool,用asynchbase
  91.         HTable table = new HTable(config, tableName);  
  92.         Get get = new Get(rowkey.getBytes()); // 根據rowkey查詢,該操作會比較費時
  93.         Result r = table.get(get);  
  94.         logger.info("結束時間");  
  95.         KeyValue[] kv = r.raw();  
  96.         for (int i = 0; i < kv.length; i++) {  
  97.             // 迴圈每一列
  98.             String key = kv[i].getKeyString();  
  99.             String value = kv[i].getValueArray().toString();  
  100.             // 將查詢到的結果寫入List中
  101.             list.add(key + ":"+ value);  
  102.         }// end of 遍歷每一列
  103.         return list;  
  104.     }