咱們常說看一張 HBase 表設計的好很差,就看它的 RowKey 設計的好很差。可見 RowKey 在 HBase 中的地位。那麼 RowKey 究竟是什麼?RowKey 的特色以下:html
若是咱們的 RowKey 設計爲 uid+phone+name,那麼這種設計能夠很好的支持如下的場景:算法
難以支持的場景:緩存
HBase 表的數據是按照 Rowkey 來分散到不一樣 Region,不合理的 Rowkey 設計會致使熱點問題。熱點問題是大量的 Client 直接訪問集羣的一個或極少數個節點,而集羣中的其餘節點卻處於相對空閒狀態。微信
如上圖,Region1 上的數據是 Region 2 的5倍,這樣會致使 Region1 的訪問頻率比較高,進而影響這個 Region 所在機器的其餘 Region。oop
咱們如何避免上面說到的熱點問題呢?這就是這章節談到的三種方法。ui
這裏的加鹽不是密碼學中的加鹽,而是在rowkey 的前面增長隨機數。具體就是給 rowkey 分配一個隨機前綴 以使得它和以前排序不一樣。分配的前綴種類數量應該和你想使數據分散到不一樣的 region 的數量一致。 若是你有一些 熱點 rowkey 反覆出如今其餘分佈均勻的 rwokey 中,加鹽是頗有用的。考慮下面的例子:它將寫請求分散到多個 RegionServers,可是對讀形成了一些負面影響。spa
假如你有下列 rowkey,你表中每個 region 對應字母表中每個字母。 以 'a' 開頭是同一個region, 'b'開頭的是同一個region。在表中,全部以 'f'開頭的都在同一個 region, 它們的 rowkey 像下面這樣:操作系統
foo0001
foo0002
foo0003
foo0004
|
如今,假如你須要將上面這個 region 分散到 4個 region。你能夠用4個不一樣的鹽:'a', 'b', 'c', 'd'.在這個方案下,每個字母前綴都會在不一樣的 region 中。加鹽以後,你有了下面的 rowkey:設計
a-foo0003
b-foo0001
c-foo0004
d-foo0002
|
因此,你能夠向4個不一樣的 region 寫。理論上說,若是這四個 Region 存放在不一樣的機器上,通過加鹽以後你將擁有以前4倍的吞吐量。code
如今,若是再增長一行,它將隨機分配a,b,c,d中的一個做爲前綴,並以一個現有行做爲尾部結束:
a-foo0003
b-foo0001
c-foo0003
c-foo0004
d-foo0002
|
由於分配是隨機的,因此若是你想要以字典序取回數據,你須要作更多工做。加鹽這種方式增長了寫時的吞吐量,可是當讀時有了額外代價。
Hashing 的原理是計算 RowKey 的 hash 值,而後取 hash 的部分字符串和原來的 RowKey 進行拼接。這裏說的 hash 包含 MD五、sha一、sha256或sha512等算法。好比咱們有以下的 RowKey:
foo0001
foo0002
foo0003
foo0004
|
咱們使用 md5 計算這些 RowKey 的 hash 值,而後取前 6 位和原來的 RowKey 拼接獲得新的 RowKey:
95f18cfoo0001
6ccc20foo0002
b61d00foo0003
1a7475foo0004
|
優缺點:能夠必定程度打散整個數據集,可是不利於 Scan;好比咱們使用 md5 算法,來計算Rowkey的md5值,而後截取前幾位的字符串。subString(MD5(設備ID), 0, x) + 設備ID,其中x通常取5或6。
Reversing 的原理是反轉一段固定長度或者所有的鍵。好比咱們有如下 URL ,並做爲 RowKey:
flink.iteblog.com
www.iteblog.com
carbondata.iteblog.com
def.iteblog.com
|
這些 URL 其實屬於同一個域名,可是因爲前面不同,致使數據不在一塊兒存放。咱們能夠對其進行反轉,以下:
moc.golbeti.knilf
moc.golbeti.www
moc.golbeti.atadnobrac
moc.golbeti.fed
|
通過這個以後,這些 URL 的數據就能夠放一塊兒了。
RowKey 能夠是任意的字符串,最大長度64KB(由於 Rowlength 佔2字節)。建議越短越好,緣由以下:
查詢某個用戶的用戶畫像數據
其中 prefix = substr(md5(uid),0 ,x), x 取 5-6。uid、idcard以及 tele 分別表示用戶惟一標識符、身份證、手機號碼。
查詢用戶最新的操做記錄或者查詢用戶某段時間的操做記錄,RowKey 設計以下:
uid + Long.Max_Value - timestamp
支持的場景
參見 《OpenTSDB 底層 HBase 的 Rowkey 是如何設計的》
若是 RowKey 沒法知足咱們的需求,能夠嘗試二級索引。Phoenix、Solr 以及 ElasticSearch 均可以用於構建二級索引。