天天看點

HBase Rowkey設計規範1.Rowkey是什麼2.Rowkey的作用3.RowKey對查詢的影響4.RowKey對Region劃分影響5.RowKey的設計技巧6.RowKey的長度7.設計案例剖析

1.Rowkey是什麼

可以了解為關系型資料庫MySQL Oracle的主鍵,用于辨別唯一的行。

完全是由使用者指定的一串不重複的字元串。

HBase中的資料永遠是根據Rowkey的字典排序來排序的。

2.Rowkey的作用

讀寫資料時 通過 RowKey 找到 對應 的 Region,例如需要查找一條資料肯定需要知道他的RowKey ,寫資料的時候也要根據RowKey 來寫。

MemStore中的資料按Rowkey字典順序排序,寫資料的時候會先将資料放到MemStore也就是記憶體,記憶體中的資料是按照Rowkey字典順序排序的。

HFile中的資料按RowKey字典順序排序,記憶體中的資料最後也會持久化到磁盤中,磁盤的資料HFile也是按RowKey字典順序排序。

3.RowKey對查詢的影響

例:RowKey由uid+phone+name組成

1.可以很好的支援的場景

  • uid=111 AND phone = 123 AND name = abc
  • uid=111 AND phone = 123
  • uid=111 AND phone = 12?
  • uid=111
    這種場景下我們都指定了uid部分,也就是RowKey的第一部分,第一種查詢的RowKey是完整的格式,是以查詢效率是最好的,後邊的三個雖然沒有指定完整RowKey,但是查詢的支援度也還不錯.           

2.難支援的場景

  • phone = 123 AND name = abc
  • phone = 123
  • name = abc
    這種場景下并沒有指定RowKey的第一部分uid,隻通過phone跟name去做查詢,也就是不指定先導部分,那麼這種場景會導緻HBase的查詢的時候去進行全表掃描,降低了查詢效率.           

4.RowKey對Region劃分影響

HBase表的資料是按照RowKey來分散到不同的Region,不合理的RowKey設計會導緻熱點問題,熱點問題是大量的Client直接通路叢集的一個或極少數個節點,而叢集中的其他節點卻處于相對空閑的狀态,進而影響對HBase表的讀寫性能.

5.RowKey的設計技巧

1.Salting(加鹽)

Salting的原理是将固定長度的随機數放在行鍵的起始處,具體就是給 rowkey 配置設定一個随機字首 以使得它和之前排序不同。配置設定的字首種類數量應該和你想使資料分散到不同的 region 的數量一緻。 如果你有一些 熱點 rowkey 反複出現在其他分布均勻的 rwokey 中,加鹽是很有用的。           

例:假如你有下列 rowkey,你表中每一個 region 對應字母表中每一個字母。 以 ‘a’ 開頭是同一個region, 'b’開頭的是同一個region。在表中,所有以 'f’開頭的都在同一個 region, 它們的 rowkey 像下面這樣:

foo0001 a-foo0001

foo0002 ===>    b-foo0002

foo0003 c-foo0003

foo0004 d-foo0004           

假如你需要将上面這個 region 分散到 4個 region。你可以用4個不同的鹽:‘a’, ‘b’, ‘c’, ‘d’.在這個方案下,每一個字母字首都會在不同的 region 中。加鹽之後,就像上邊的例子.

是以,你可以向4個不同的 region 寫,理論上說,如果所有人都向同一個region 寫的話,你将擁有之前4倍的吞吐量。

優缺點:由于字首是随機生成的,是以想要按照字典順序找到這些行,則需要做更多的工作,從這個角度上看,salting增加了寫操作的吞吐量,卻也增加了讀操作的開銷.           

2.Hashing

Hashing 的原理是計算 RowKey 的 hash 值,然後取 hash 的部分字元串和原來的 RowKey 進行拼接。這裡說的 hash 包含 MD5、sha1、sha256或sha512等算法,并不是僅限于Java的Hash值計算。

例:比如我們有如下的 RowKey:

foo0001                 95f18cfoo0001

                foo0002     ===>        6ccc20foo0002

                foo0003                 b61d00foo0003

                foo0004                 1a7475foo0004           

我們使用 md5 計算這些 RowKey 的 hash 值,然後取前 6 位和原來的 RowKey 拼接得到新的 RowKey,如上

優缺點:可以一定程度打散整個資料集,但是不利于 Scan;比如我們使用 md5 算法,來計算Rowkey的md5值,然後截取前幾位的字元串。
常見用法:subString(MD5(裝置ID), 0, x) + 裝置ID,其中x一般取5或6。           

3.Reversing(反轉)

Reversing 的原理是反轉一段固定長度或者全部的鍵。           

例:比如我們有以下 URL ,并作為 RowKey:

flink.iteblog.com                           moc.golbeti.knilf
                www.iteblog.com          ===>               moc.golbeti.www
                carbondata.iteblog.com                      moc.golbeti.atadnobrac
                def.iteblog.com                             moc.golbeti.fed           

這些 URL 其實屬于同一個域名,但是由于前面不一樣,導緻資料不在一起存放。我們可以對其進行反轉,如上,經過這個之後,字首就相同了,這些 URL 的資料就可以放一起了。

優缺點:有效的打亂了行鍵,但是卻犧牲了行排序的屬性.           

6.RowKey的長度

RowKey 可以是任意的字元串,最大長度64KB(因為 Rowlength 占2位元組)。建議越短越好,原因如下:

  • 資料的持久化檔案HFile中是按照KeyValue存儲的,如果rowkey過長,比如超過100位元組,1000w行資料,光rowkey就要占用100*1000w=10億個位元組,将近1G資料,這樣會極大影響HFile的存儲效率;
  • MemStore将緩存部分資料到記憶體,如果rowkey字段過長,記憶體的有效使用率就會降低,系統不能緩存更多的資料,這樣會降低檢索效率;
  • 目前作業系統都是64位系統,記憶體8位元組對齊,控制在16個位元組,8位元組的整數倍利用了作業系統的最佳特性。

7.設計案例剖析

1.交易類表 Rowkey 設計

  • 查詢某個賣家某段時間内的交易記錄

    sellerId + timestamp + orderId

  • 查詢某個買家某段時間内的交易記錄

    buyerId + timestamp +orderId

  • 根據訂單号查詢

    orderNo

如果某個商家賣了很多商品,按第一種方式,就有可能會有大量RowKey字首相同的資料在相同的Region上,造成熱點問題,可以如下設計 Rowkey 實作快速搜尋 salt + sellerId + timestamp 其中,salt 是随機數。

我們在原來的結構之前進行了一步加鹽salt操作,例如加上一個随機數,這樣就可以把這些資料分散到不同的Region上去了.               

可以支援的場景:

  • 全表 Scan,因為進行了加鹽操作,資料分散到了不同的Region上,Scan的時候就會去不同的Region上去Scan,這樣就提升高并發,也就提升檢索效率.
  • 按照 sellerId 查詢
  • 按照 sellerId + timestamp 查詢

2.金融風控 Rowkey 設計

查詢某個使用者的使用者畫像資料

prefix + uid

prefix + idcard

prefix + tele           

其中字首的生成 prefix = substr(md5(uid),0 ,x), x 取 5-6。uid、idcard以及 tele 分别表示使用者唯一辨別符、×××、手機号碼。

3.車聯網 Rowkey 設計

  • 查詢某輛車在某個時間範圍的資料,例如發動機資料

    carId + timestamp

  • 某批次的車太多,造成熱點

    prefix + carId + timestamp

其中 prefix = substr(md5(uid),0 ,x)

4.倒序時間戳(時間倒排)

查詢使用者最新的操作記錄或者查詢使用者某段時間的操作記錄,RowKey 設計如下:

uid + Long.Max_Value - timestamp

支援的場景

  • 查詢使用者最新的操作記錄

    Scan [uid] startRow [uid][00000000000] stopRow [uid][uid][Long.Max_Value - timestamp]

    這樣就能查出比如說最近100條資料

  • 查詢使用者某段時間的操作記錄

    Scan [uid] startRow [uid][Long.Max_Value - startTime] stopRow uid [uid][Long.Max_Value - endTime]

5.二級索引

例:有一張HBase表結構及資料如下

HBase Rowkey設計規範1.Rowkey是什麼2.Rowkey的作用3.RowKey對查詢的影響4.RowKey對Region劃分影響5.RowKey的設計技巧6.RowKey的長度7.設計案例剖析

問:如何查找phone=13111111111的使用者?

遇到這種需求的時候,HBase的設計肯定是滿足不了的,這時候就要引入二級索引,将phone當做RowKey,uid/name當做列名建構二級索引.

繼續閱讀