Hbase Rowkey设计原则
Hbase是三維有序存儲的,通過rowkey(行鍵),column key(column family和qualifier)和TimeStamp(時間戳)這三個維度可以對HBase中的數據進行快速定位。
?
Hbase中Rowkey可以唯一標識一行記錄,在Hbase查詢的時候,有以下幾種方式:
1、通過get方式,指定rowkey獲取唯一一條記錄
2、通過scan方式,設置StartRow和EndRow參數進行范圍匹配
3、全表掃描,即直接掃描整張表中所有行記錄
Rowkey長度原則
rowkey是一個二進制碼流,可以是任意字符串,最大長度?64kb?,實際應用中一般為10-100bytes,以?byte[]?形式保存,一般設計成定長。
建議越短越好,不要超過16個字節,原因如下:
rowkey散列原則
如果rowkey按照時間戳的方式遞增,不要將時間放在二進制碼的前面,建議將rowkey的高位作為散列字段,由程序隨機生成,低位放時間字段,這樣將提高數據均衡分布在每個RegionServer,以實現負載均衡的幾率。如果沒有散列字段,首字段直接是時間信息,所有的數據都會集中在一個RegionServer上,這樣在數據檢索的時候負載會集中在個別的RegionServer上,造成熱點問題,會降低查詢效率。
rowkey唯一原則
必須在設計上保證其唯一性,rowkey是按照字典順序排序存儲的,因此,設計rowkey的時候,要充分利用這個排序的特點,將經常讀取的數據存儲到一塊,將最近可能會被訪問的數據放到一塊。
什么是熱點
HBase中的行是按照rowkey的字典順序排序的,這種設計優化了scan操作,可以將相關的行以及會被一起讀取的行存取在臨近位置,便于scan。然而糟糕的rowkey設計是熱點的源頭。 熱點發生在大量的client直接訪問集群的一個或極少數個節點(訪問可能是讀,寫或者其他操作)。大量訪問會使熱點region所在的單個機器超出自身承受能力,引起性能下降甚至region不可用,這也會影響同一個RegionServer上的其他region,由于主機無法服務其他region的請求。 設計良好的數據訪問模式以使集群被充分,均衡的利用。
為了避免寫熱點,設計rowkey使得不同行在同一個region,但是在更多數據情況下,數據應該被寫入集群的多個region,而不是一個。
?
常見的避免熱點的方法以及它們的優缺點:
1、鹽析
在rowkey的前面增加隨機數,具體就是給rowkey分配一個隨機前綴以使得它和之前的rowkey的開頭不同。分配的前綴種類數量應該和你想使用數據分散到不同的region的數量一致。加鹽之后的rowkey就會根據隨機生成的前綴分散到各個region上,以避免熱點。
2、哈希
哈希會使同一行永遠用一個前綴加鹽。哈希也可以使負載分散到整個集群,但是讀卻是可以預測的。使用確定的哈希可以讓客戶端重構完整的rowkey,可以使用get操作準確獲取某一個行數據
3、反轉
第三種防止熱點的方法時反轉固定長度或者數字格式的rowkey。這樣可以使得rowkey中經常改變的部分(最沒有意義的部分)放在前面。這樣可以有效的隨機rowkey,但是犧牲了rowkey的有序性。
反轉rowkey的例子以手機號為rowkey,可以將手機號反轉后的字符串作為rowkey,這樣的就避免了以手機號那樣比較固定開頭導致熱點問題
4、時間戳反轉
一個常見的數據處理問題是快速獲取數據的最近版本,使用反轉的時間戳作為rowkey的一部分對這個問題十分有用,可以用?Long.Max_Value - timestamp?追加到key的末尾,例如?[key][reverse_timestamp]?,?[key]?的最新值可以通過scan [key]獲得[key]的第一條記錄,因為HBase中rowkey是有序的,第一條記錄是最后錄入的數據。
比如需要保存一個用戶的操作記錄,按照操作時間倒序排序,在設計rowkey的時候,可以這樣設計
[userId反轉][Long.Max_Value - timestamp],在查詢用戶的所有操作記錄數據的時候,直接指定反轉后的userId,startRow是[userId反轉][000000000000],stopRow是[userId反轉][Long.Max_Value - timestamp]
如果需要查詢某段時間的操作記錄,startRow是[user反轉][Long.Max_Value - 起始時間],stopRow是[userId反轉][Long.Max_Value - 結束時間]
5、建表時進行預分區處理
?默認情況下,在創建Hbase表的時候會自動創建一個region分區,當導入數據的時候,所有的HBase客戶端都向這一個Region寫數據,知道這個Region足夠大了才進行切分。我們通過預先創建一些空的Regions,這樣當數據寫入Hbase時,會按照region分區情況,在集群內做數據的負載均衡。
1、命令方式:
# create table with specific split points hbase>create 'table1','f1',SPLITS => ['\x10\x00', '\x20\x00', '\x30\x00', '\x40\x00'] # create table with four regions based on random bytes keys hbase>create 'table2','f1', { NUMREGIONS => 8 , SPLITALGO => 'UniformSplit' } # create table with five regions based on hex keys hbase>create 'table3','f1', { NUMREGIONS => 10, SPLITALGO => 'HexStringSplit' }2、API方式
hbase org.apache.hadoop.hbase.util.RegionSplitter test_table HexStringSplit -c 10 -f infohbase org.apache.hadoop.hbase.util.RegionSplitter splitTable HexStringSplit -c 10 -f info參數:
test_table 是表名
HexStringSplit 是split 方式
-c 是分 10 個 region
-f 是 family
這樣就可以將表預先分為 10 個區,減少數據達到 storefile 大小的時候自動分區的時間 消耗,并且還有以一個優勢,就是合理設計 rowkey 能讓各個 region 的并發請求平均分配(趨 于均勻) 使 IO 效率達到最高,但是預分區需要將 filesize 設置一個較大的值,設置哪個參數 呢 hbase.hregion.max.filesize 這個值默認是 10G 也就是說單個 region 默認大小是 10G
這個參數的默認值在 0.90 到 0.92 到 0.94.3 各版本的變化:256M--1G--10G
但是如果 MapReduce Input 類型為 TableInputFormat 使用 hbase 作為輸入的時候,就要注意 了,每個 region 一個 map,如果數據小于 10G 那只會啟用一個 map 造成很大的資源浪費, 這時候可以考慮適當調小該參數的值,或者采用預分配 region 的方式,并將檢測如果達到 這個值,再手動分配 region。
轉載于:https://www.cnblogs.com/yfb918/p/10600898.html
總結
以上是生活随笔為你收集整理的Hbase Rowkey设计原则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有趣的反直觉的“三门问题”
- 下一篇: 《流畅的python》概述