HBase學習之五:HBase的RowKey設計原則
Hbase是三維有序存儲的,通過rowkey(行鍵),column key(column family和qualifier)和TimeStamp(時間戳)這個三個維度可以對hbase中的數據進行快速定位。
HBase中rowkey可以唯一標識一行記錄,在HBase查詢的時候,有以下幾種方式:
- 通過get方式,指定rowkey獲取唯一一條記錄
- 通過scan方式,設置startRow和stopRow參數進行範圍匹配
- 全表掃描,即直接掃描整張表中所有行記錄
rowkey長度原則
rowkey是一個二進製碼流,可以是任意字符串,最大長度 64kb ,實際應用中一般為10-100bytes,以 byte[]
形式保存,一般設計成定長。
建議越短越好,不要超過16個字節,原因如下:
- 數據的持久化文件HFile中是按照KeyValue存儲的,如果rowkey過長,比如超過100字節,1000w行數據,光rowkey就要占用100*1000w=10億個字節,將近1G數據,這樣會極大影響HFile的存儲效率;
- MemStore將緩存部分數據到內存,如果rowkey字段過長,內存的有效利用率就會降低,係統不能緩存更多的數據,這樣會降低檢索效率。
- 目前操作係統都是64位係統,內存8字節對齊,控製在16個字節,8字節的整數倍利用了操作係統的最佳特性。
rowkey散列原則
如果rowkey按照時間戳的方式遞增,不要將時間放在二進製碼的前麵,建議將rowkey的高位作為散列字段,由程序隨機生成,低位放時間字段,這樣將提高數據均衡分布在每個RegionServer,以實現負載均衡的幾率。如果沒有散列字段,首字段直接是時間信息,所有的數據都會集中在一個RegionServer上,這樣在數據檢索的時候負載會集中在個別的RegionServer上,造成熱點問題,會降低查詢效率。
rowkey唯一原則
必須在設計上保證其唯一性,rowkey是按照字典順序排序存儲的,因此,設計rowkey的時候,要充分利用這個排序的特點,將經常讀取的數據存儲到一塊,將最近可能會被訪問的數據放到一塊。
什麼是熱點
HBase中的行是按照rowkey的字典順序排序的,這種設計優化了scan操作,可以將相關的行以及會被一起讀取的行存取在臨近位置,便於scan。然而糟糕的rowkey設計是熱點的源頭。 熱點發生在大量的client直接訪問集群的一個或極少數個節點(訪問可能是讀,寫或者其他操作)。大量訪問會使熱點region所在的單個機器超出自身承受能力,引起性能下降甚至region不可用,這也會影響同一個RegionServer上的其他region,由於主機無法服務其他region的請求。 設計良好的數據訪問模式以使集群被充分,均衡的利用。
為了避免寫熱點,設計rowkey使得不同行在同一個region,但是在更多數據情況下,數據應該被寫入集群的多個region,而不是一個。
下麵是一些常見的避免熱點的方法以及它們的優缺點:
加鹽
這裏所說的加鹽不是密碼學中的加鹽,而是在rowkey的前麵增加隨機數,具體就是給rowkey分配一個隨機前綴以使得它和之前的rowkey的開頭不同。分配的前綴種類數量應該和你想使用數據分散到不同的region的數量一致。加鹽之後的rowkey就會根據隨機生成的前綴分散到各個region上,以避免熱點。
哈希
哈希會使同一行永遠用一個前綴加鹽。哈希也可以使負載分散到整個集群,但是讀卻是可以預測的。使用確定的哈希可以讓客戶端重構完整的rowkey,可以使用get操作準確獲取某一個行數據
反轉
第三種防止熱點的方法時反轉固定長度或者數字格式的rowkey。這樣可以使得rowkey中經常改變的部分(最沒有意義的部分)放在前麵。這樣可以有效的隨機rowkey,但是犧牲了rowkey的有序性。
反轉rowkey的例子以手機號為rowkey,可以將手機號反轉後的字符串作為rowkey,這樣的就避免了以手機號那樣比較固定開頭導致熱點問題
時間戳反轉
一個常見的數據處理問題是快速獲取數據的最近版本,使用反轉的時間戳作為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 - 結束時間]
其他一些建議
-
盡量減少行和列的大小在HBase中,value永遠和它的key一起傳輸的。當具體的值在係統間傳輸時,它的rowkey,列名,時間戳也會一起傳輸。如果你的rowkey和列名很大,甚至可以和具體的值相比較,那麼你將會遇到一些有趣的問題。HBase storefiles中的索引(有助於隨機訪問)最終占據了HBase分配的大量內存,因為具體的值和它的key很大。可以增加block大小使得storefiles索引再更大的時間間隔增加,或者修改表的模式以減小rowkey和列名的大小。壓縮也有助於更大的索引。
-
列族盡可能越短越好,最好是一個字符
-
冗長的屬性名雖然可讀性好,但是更短的屬性名存儲在HBase中會更好
最後更新:2017-06-21 22:01:53
上一篇:
逼死強迫症?聊聊應用推送角標的那些事兒
下一篇:
程序員有哪些強迫症?聽知乎網友為你現身說法
Juniper推出基於雲的全球攻擊者數據庫
Modern Web Identity: Why Your Web Applications Should Be Offering OpenID, OAuth, And Probably Facebook Connect
java中short s=s+1和s+=1的區別
從軟件公司的企業文化淺談什麼是管理能力
存儲--盤古,阿裏雲飛天分布式存儲係統設計深度解析
【Linux shell】sed實踐(1)
一個核物理學霸為何兩次收到BlackHat的邀請
Apache/Nginx+PHP+MySQL一鍵環境安裝包
揭秘雲棲大會VR直播雲服務解決方案的技術亮點和核心能力
東南大學高桓:知識圖譜表示學習 | 直播預告·PhD Talk #15