案例篇-HBase RowKey 设计指南
1.為什么 Rowkey 這么重要
1.1 RowKey 到底是什么
我們常說看一張 HBase 表設(shè)計(jì)的好不好,就看它的 RowKey 設(shè)計(jì)的好不好。可見 RowKey 在 HBase 中的地位。那么 RowKey 到底是什么?RowKey 的特點(diǎn) 如下:
1.2 RowKey 的作用
1.3 Rowkey 對(duì)查詢的影響
如果我們的 RowKey 設(shè)計(jì)為 uid+phone+name,那么這種設(shè)計(jì)可以很好的支持
以下的場(chǎng)景:
uid = 111 AND phone = 123 AND name = iteblog uid = 111 AND phone = 123
uid = 111 AND phone = 12?
uid = 111
難以支持的場(chǎng)景:
phone = 123 AND name = iteblog phone = 123
name = iteblog
1.4 Rowkey 對(duì) Region 劃分影響
HBase表的數(shù)據(jù)是按照 Rowkey 來分散到不同 Region,不合理的 Rowkey 設(shè)計(jì)會(huì)導(dǎo)致熱點(diǎn)問題。熱點(diǎn)問題是大量的 Client 直接訪問集群的一個(gè)或極少數(shù)個(gè)節(jié)點(diǎn),而集群中的其他節(jié)點(diǎn)卻處于相對(duì)空閑狀態(tài)。
如上圖,Region1 上的數(shù)據(jù)是 Region 2 的 5 倍,這樣會(huì)導(dǎo)致 Region1 的訪問 頻率比較高,進(jìn)而影響這個(gè) Region 所在機(jī)器的其他 Region。
2.RowKey 設(shè)計(jì)技巧
我們?nèi)绾伪苊馍厦嬲f到的熱點(diǎn)問題呢?這就是這章節(jié)談到的三種方法。
2.1 避免熱點(diǎn)的方法 – Salting
這里的加鹽不是密碼學(xué)中的加鹽,而是在 rowkey 的前面增加隨機(jī)數(shù)。具體就是給 rowkey 分配一個(gè)隨機(jī)前綴以使得它和之前排序不同。分配的前綴種類數(shù)量應(yīng)該和你想使數(shù)據(jù)分散到不同的 region 的數(shù)量一致。 如果你有一些 熱點(diǎn) rowkey 反復(fù)出現(xiàn)在其他分布均勻的 rwokey 中,加鹽是很有用的。考慮下面的例子:它將寫請(qǐng)求分散到多個(gè)RegionServers,但是對(duì)讀造成了一些負(fù)面影響。
假如你有下列 rowkey,你表中每一個(gè) region 對(duì)應(yīng)字母表中每一個(gè)字母。以 'a' 開頭是同一個(gè) region, 'b'開頭的是同一個(gè) region。在表中,所有以 'f'開頭的都在 同一個(gè) region, 它們的 rowkey 像下面這樣:
現(xiàn)在,假如你需要將上面這個(gè) region 分散到 4 個(gè) region。你可以用 4 個(gè)不同 的鹽:'a', 'b', 'c', 'd'.在這個(gè)方案下,每一個(gè)字母前綴都會(huì)在不同的 region 中。 加鹽之后,你有了下面的 rowkey:
所以,你可以向 4 個(gè)不同的 region 寫,理論上說,如果所有人都向同一個(gè) region 寫的話,你將擁有之前 4 倍的吞吐量。
現(xiàn)在,如果再增加一行,它將隨機(jī)分配 a,b,c,d 中的一個(gè)作為前綴,并以一個(gè)現(xiàn)有行作為尾部結(jié)束:
因?yàn)榉峙涫请S機(jī)的,所以如果你想要以字典序取回?cái)?shù)據(jù),你需要做更多工作。加鹽這種方式增加了寫時(shí)的吞吐量,但是當(dāng)讀時(shí)有了額外代價(jià)。
2.2 避免熱點(diǎn)的方法 - Hashing
Hashing 的原理是計(jì)算 RowKey 的 hash 值,然后取 hash 的部分字符串和原來的 RowKey 進(jìn)行拼接。這里說的 hash 包含 MD5、sha1、sha256 或 sha512 等算法。比如我們有如下的 RowKey:
我們使用 md5 計(jì)算這些 RowKey 的 hash 值,然后取前 6 位和原來的 RowKey 拼接得到新的 RowKey:
優(yōu)缺點(diǎn):可以一定程度打散整個(gè)數(shù)據(jù)集,但是不利于 Scan;比如我們使用 md5 算法,來計(jì)算 Rowkey 的 md5 值,然后截取前幾位的字符串。subString(MD5(設(shè)備ID),0,x)+ 設(shè)備ID,其中x一般取5或6。
2.3 避免熱點(diǎn)的方法 - Reversing
Reversing 的原理是反轉(zhuǎn)一段固定長度或者全部的鍵。比如我們有以下 URL , 并作為 RowKey:
這些 URL 其實(shí)屬于同一個(gè)域名,但是由于前面不一樣,導(dǎo)致數(shù)據(jù)不在一起存放。 我們可以對(duì)其進(jìn)行反轉(zhuǎn),如下:
經(jīng)過這個(gè)之后,這些 URL 的數(shù)據(jù)就可以放一起了。
2.4 RowKey 的長度
RowKey 可以是任意的字符串,最大長度 64KB(因?yàn)?Rowlength 占 2 字節(jié))。 建議越短越好,原因如下:
3.RowKey 設(shè)計(jì)案例剖析
3.1 交易類表 Rowkey 設(shè)計(jì)
查詢某個(gè)賣家某段時(shí)間內(nèi)的交易記錄
sellerId + timestamp + orderId
查詢某個(gè)買家某段時(shí)間內(nèi)的交易記錄
buyerId + timestamp +orderId
根據(jù)訂單號(hào)查詢 orderNo
如果某個(gè)商家賣了很多商品,可以如下設(shè)計(jì) Rowkey 實(shí)現(xiàn)快速搜索salt+sellerId + timestamp 其中,salt 是隨機(jī)數(shù)。
可以支持的場(chǎng)景:
3.2 金融風(fēng)控 Rowkey 設(shè)計(jì)
查詢某個(gè)用戶的用戶畫像數(shù)據(jù)
其中 prefix = substr(md5(uid),0 ,x), x 取 5-6。uid、idcard 以及 tele 分別表示 用戶唯一標(biāo)識(shí)符、身份證、手機(jī)號(hào)碼。
3.3 車聯(lián)網(wǎng) Rowkey 設(shè)計(jì) 查詢某輛車在某個(gè)時(shí)間范圍的交易記錄
carId + timestamp
某批次的車太多,造成熱點(diǎn)
prefix + carId + timestamp 其中 prefix = substr(md5(uid),0 ,x)
3.4 查詢最近的數(shù)據(jù)
查詢用戶最新的操作記錄或者查詢用戶某段時(shí)間的操作記錄,RowKey 設(shè)計(jì)如下: uid + Long.Max_Value - timestamp
支持的場(chǎng)景
查詢用戶最新的操作記錄
Scan [uid] startRow uid stopRow uid
查詢用戶某段時(shí)間的操作記錄
Scan [uid] startRow uid stopRow uid
如果 RowKey 無法滿足我們的需求,可以嘗試二級(jí)索引。Phoenix、Solr 以及 ElasticSearch 都可以用于構(gòu)建二級(jí)索引。
總結(jié)
以上是生活随笔為你收集整理的案例篇-HBase RowKey 设计指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【企业架构】什么是 Zachman 框架
- 下一篇: 播音员主持人训练