[RowKey]HBase的RowKey設(shè)計(jì)原則

HBase學(xué)習(xí)之五:HBase的RowKey設(shè)計(jì)原則 - To be a nice Man - 博客頻道 - CSDN.NET http://blog.csdn.net/javajxz008/article/details/51892967

Hbase是三維有序存儲的,通過rowkey(行鍵),column key(column family和qualifier)和TimeStamp(時間戳)這個三個維度可以對HBase中的數(shù)據(jù)進(jìn)行快速定位。
HBase中rowkey可以唯一標(biāo)識一行記錄,在HBase查詢的時候,有以下幾種方式:
通過get方式,指定rowkey獲取唯一一條記錄
通過scan方式,設(shè)置startRow和stopRow參數(shù)進(jìn)行范圍匹配
全表掃描,即直接掃描整張表中所有行記錄

rowkey長度原則
rowkey是一個二進(jìn)制碼流,可以是任意字符串,最大長度 64kb ,實(shí)際應(yīng)用中一般為10-100bytes,以 byte[]
形式保存,一般設(shè)計(jì)成定長。
建議越短越好,不要超過16個字節(jié),原因如下:

數(shù)據(jù)的持久化文件HFile中是按照KeyValue存儲的,如果rowkey過長,比如超過100字節(jié),1000w行數(shù)據(jù),光rowkey就要占用100*1000w=10億個字節(jié),將近1G數(shù)據(jù),這樣會極大影響HFile的存儲效率;
MemStore將緩存部分?jǐn)?shù)據(jù)到內(nèi)存,如果rowkey字段過長,內(nèi)存的有效利用率就會降低,系統(tǒng)不能緩存更多的數(shù)據(jù),這樣會降低檢索效率。
目前操作系統(tǒng)都是64位系統(tǒng),內(nèi)存8字節(jié)對齊,控制在16個字節(jié),8字節(jié)的整數(shù)倍利用了操作系統(tǒng)的最佳特性。

rowkey散列原則
如果rowkey按照時間戳的方式遞增,不要將時間放在二進(jìn)制碼的前面,建議將rowkey的高位作為散列字段,由程序隨機(jī)生成,低位放時間字段,這樣將提高數(shù)據(jù)均衡分布在每個RegionServer,以實(shí)現(xiàn)負(fù)載均衡的幾率。如果沒有散列字段,首字段直接是時間信息,所有的數(shù)據(jù)都會集中在一個RegionServer上,這樣在數(shù)據(jù)檢索的時候負(fù)載會集中在個別的RegionServer上,造成熱點(diǎn)問題,會降低查詢效率。
rowkey唯一原則
必須在設(shè)計(jì)上保證其唯一性,rowkey是按照字典順序排序存儲的,因此,設(shè)計(jì)rowkey的時候,要充分利用這個排序的特點(diǎn),將經(jīng)常讀取的數(shù)據(jù)存儲到一塊,將最近可能會被訪問的數(shù)據(jù)放到一塊。
什么是熱點(diǎn)
HBase中的行是按照rowkey的字典順序排序的,這種設(shè)計(jì)優(yōu)化了scan操作,可以將相關(guān)的行以及會被一起讀取的行存取在臨近位置,便于scan。然而糟糕的rowkey設(shè)計(jì)是熱點(diǎn)的源頭。 熱點(diǎn)發(fā)生在大量的client直接訪問集群的一個或極少數(shù)個節(jié)點(diǎn)(訪問可能是讀,寫或者其他操作)。大量訪問會使熱點(diǎn)region所在的單個機(jī)器超出自身承受能力,引起性能下降甚至region不可用,這也會影響同一個RegionServer上的其他region,由于主機(jī)無法服務(wù)其他region的請求。 設(shè)計(jì)良好的數(shù)據(jù)訪問模式以使集群被充分,均衡的利用。
為了避免寫熱點(diǎn),設(shè)計(jì)rowkey使得不同行在同一個region,但是在更多數(shù)據(jù)情況下,數(shù)據(jù)應(yīng)該被寫入集群的多個region,而不是一個。
下面是一些常見的避免熱點(diǎn)的方法以及它們的優(yōu)缺點(diǎn):
加鹽
這里所說的加鹽不是密碼學(xué)中的加鹽,而是在rowkey的前面增加隨機(jī)數(shù),具體就是給rowkey分配一個隨機(jī)前綴以使得它和之前的rowkey的開頭不同。分配的前綴種類數(shù)量應(yīng)該和你想使用數(shù)據(jù)分散到不同的region的數(shù)量一致。加鹽之后的rowkey就會根據(jù)隨機(jī)生成的前綴分散到各個region上,以避免熱點(diǎn)。
哈希
哈希會使同一行永遠(yuǎn)用一個前綴加鹽。哈希也可以使負(fù)載分散到整個集群,但是讀卻是可以預(yù)測的。使用確定的哈??梢宰尶蛻舳酥貥?gòu)完整的rowkey,可以使用get操作準(zhǔn)確獲取某一個行數(shù)據(jù)
反轉(zhuǎn)
第三種防止熱點(diǎn)的方法時反轉(zhuǎn)固定長度或者數(shù)字格式的rowkey。這樣可以使得rowkey中經(jīng)常改變的部分(最沒有意義的部分)放在前面。這樣可以有效的隨機(jī)rowkey,但是犧牲了rowkey的有序性。
反轉(zhuǎn)rowkey的例子以手機(jī)號為rowkey,可以將手機(jī)號反轉(zhuǎn)后的字符串作為rowkey,這樣的就避免了以手機(jī)號那樣比較固定開頭導(dǎo)致熱點(diǎn)問題
時間戳反轉(zhuǎn)
一個常見的數(shù)據(jù)處理問題是快速獲取數(shù)據(jù)的最近版本,使用反轉(zhuǎn)的時間戳作為rowkey的一部分對這個問題十分有用,可以用 Long.Max_Value - timestamp
追加到key的末尾,例如 [key][reverse_timestamp]
, [key]
的最新值可以通過scan [key]獲得[key]的第一條記錄,因?yàn)镠Base中rowkey是有序的,第一條記錄是最后錄入的數(shù)據(jù)。
比如需要保存一個用戶的操作記錄,按照操作時間倒序排序,在設(shè)計(jì)rowkey的時候,可以這樣設(shè)計(jì)
[userId反轉(zhuǎn)][Long.Max_Value - timestamp],在查詢用戶的所有操作記錄數(shù)據(jù)的時候,直接指定反轉(zhuǎn)后的userId,startRow是[userId反轉(zhuǎn)][000000000000],stopRow是[userId反轉(zhuǎn)][Long.Max_Value - timestamp]
如果需要查詢某段時間的操作記錄,startRow是[user反轉(zhuǎn)][Long.Max_Value - 起始時間],stopRow是[userId反轉(zhuǎn)][Long.Max_Value - 結(jié)束時間]

其他一些建議
盡量減少行和列的大小在HBase中,value永遠(yuǎn)和它的key一起傳輸?shù)摹.?dāng)具體的值在系統(tǒng)間傳輸時,它的rowkey,列名,時間戳也會一起傳輸。如果你的rowkey和列名很大,甚至可以和具體的值相比較,那么你將會遇到一些有趣的問題。HBase storefiles中的索引(有助于隨機(jī)訪問)最終占據(jù)了HBase分配的大量內(nèi)存,因?yàn)榫唧w的值和它的key很大。可以增加block大小使得storefiles索引再更大的時間間隔增加,或者修改表的模式以減小rowkey和列名的大小。壓縮也有助于更大的索引。

列族盡可能越短越好,最好是一個字符

冗長的屬性名雖然可讀性好,但是更短的屬性名存儲在HBase中會更好

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容