溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

HBase怎么設計rowkey

發(fā)布時間:2021-12-08 14:19:43 來源:億速云 閱讀:213 作者:小新 欄目:大數(shù)據(jù)

這篇文章主要為大家展示了“HBase怎么設計rowkey”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“HBase怎么設計rowkey”這篇文章吧。

HBase中的rowkey是按字典順序排序的,通過rowkey查詢可以對千萬級的數(shù)據(jù)實現(xiàn)毫秒級響應。然而,如果rowkey設計不合理的話經(jīng)常會出現(xiàn)一個很普遍的問題----熱點。當大量client的請求(讀或者寫)只指向集群的一個節(jié)點,或者很少量的幾個節(jié)點時,也就代表產(chǎn)生了熱點問題。

避免產(chǎn)生熱點的方式也就是盡可能的將rowkey均勻分散到所有的region上,下面介紹了幾種rowkey設計常用的方式:

 

第一:加鹽(salting)

加鹽是指在rowkey的前綴添加隨機數(shù)據(jù),使rowkey盡可能的分布到其他regionserver上

假設遇到下面的rowkey,表的預分區(qū)設置為每個字母對應一個region。前綴“a”是一個region,前綴“b”是另一個region等等。那么在這個表中,所有以“f”開頭的rowkey都將位于同一個region。比如:

foo0001

foo0002

foo0003

foo0004
 

那么,如果你想把它們分散到四個不同的region,那么就可以使用四種不同的前綴: a、b、c和d來做加鹽。在加鹽之后,rowkey也就變成了下面這樣。

a-foo0003

b-foo0001

c-foo0004

d-foo0002
 

(ps:由于現(xiàn)在可以向四個region寫數(shù)據(jù),理論上,性能比之前向同一個region寫吞吐量提升四倍)

并且,如果后續(xù)有新的數(shù)據(jù)寫入,rowkey也就會隨機的添加前綴,寫到不同的region中

缺點:加鹽雖然可以很大程度的避免熱點問題,提升寫入效率,但是由于rowkey被隨機的添加了salt值,在讀取時候要付出額外的開銷。具體怎么讀取加鹽后的數(shù)據(jù),后面再做介紹

 

第二:哈希(hashing)

哈希的算法有多種,在rowkey設計中用的比較多的大概就是MD5了吧,但是需要注意的是MD5散列還是有碰撞的可能性的,概率很小,但是不是零。

所以一般使用MD5做rowkey散列時候,都會附加一個唯一字段,比如賬號字段account,對account做MD5,截取6位左右的md5返回值然后再拼接account字段,也就是:

substr(md5(account))+account
 

此外,通過md5散列之后的rowkey,在創(chuàng)建表預分區(qū)時候,可以使用hbase自帶的HexStringSplit方法

 

第三:反轉(Reversing)

如果定義的rowkey字段,前部分數(shù)據(jù)變化幅度很小,變化很慢,尾部數(shù)據(jù)變化頻率較高,便可以考慮反轉字段,尤其對類似時間戳的數(shù)據(jù)

不管以哪種方式設計rowkey,在查詢時候也要做對應的數(shù)據(jù)處理,比如做hash的,查詢時候也需要先把數(shù)據(jù)hash之后,然后查詢rowkey;通過反轉方式設計的rowkey同理。

 

第四:最小化rowkey和列簇長度

rowkey可以是任意的字符串,最大長度64KB,但是建議在設計rowkey時候,盡可能的短,原因:

1.hbase數(shù)據(jù)存儲是以key-value的形式存儲的,如果rowkey比較長,比如100字節(jié),那么1000w行數(shù)據(jù),光rowkey存儲就需要100*1000w=10億個字節(jié),將近1G的數(shù)據(jù)。

2.memstore的會緩存數(shù)據(jù)到內存,如果rowkey比較長,同樣會占用更多的空間

3.建議rowkey設計在8字節(jié)的整數(shù)倍,控制在16個字節(jié),因為目前的操作系統(tǒng)大多都是64位的,整數(shù)倍更好了利用了操作系統(tǒng)的特性。

列簇(ColumnFamily)同理,盡可能的短,最好是一個字符,比如 f 或者 d

 

第五:Byte Patterns

我們知道,long類型是8個字節(jié),并且你可以通過long類型存儲一個最大為18,446,744,073,709,551,615的無符號數(shù)字,僅僅用8個字節(jié),但是如果以string類型的形式存儲這樣的數(shù)字,那么幾乎需要3倍空間的大?。俣總€字符占一個字節(jié))

舉個例子驗證一下:

// long
//
long l = 1234567890L;
byte[] lb = Bytes.toBytes(l);
System.out.println("long bytes length: " + lb.length);   // returns 8

String s = String.valueOf(l);
byte[] sb = Bytes.toBytes(s);
System.out.println("long as string length: " + sb.length);    // returns 10

// hash
//
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(Bytes.toBytes(s));
System.out.println("md5 digest bytes length: " + digest.length);    // returns 16

String sDigest = new String(digest);
byte[] sbDigest = Bytes.toBytes(sDigest);
System.out.println("md5 digest as string length: " + sbDigest.length);    // returns 26
 

但是,也有一個缺點,就是如果使用這種二進制表示的類型時候,在hbase shell界面查數(shù)據(jù)的時候,可讀性比較差,比如:

hbase(main):002:0> get 'table1', 'rowkey1'
COLUMN                                        CELL
 f:q                                          timestamp=1369163040570, value=\x00\x00\x00\x00\x00\x00\x00\x01
1 row(s) in 0.0310 seconds

以上是“HBase怎么設計rowkey”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI