一篇文章帶你快速搞懂HBase RowKey設計


前面和大家分享了一些HBase入門基礎知識。HBase作為一個數據庫,在使用中無外乎增刪改查操作,這些操作在HBase中都是和RowKey緊密相關的,所以優秀的RowKey設計方案是非常重要的。今天就來說說如何進行HBase的RowKey的設計。

RowKey的作用

RowKey在查詢中的作用

HBase中RowKey可以唯一標識一行記錄,在HBase中檢索數據有以下三種方式:

  1. 通過 get 方式,指定 RowKey 獲取唯一一條記錄

  2. 通過 scan 方式,設置 startRow 和 stopRow 參數進行范圍匹配

  3. 全表掃描,即直接掃描整張表中所有行記錄

當大量請求訪問HBase集群的一個或少數幾個節點,造成少數RegionServer的讀寫請求過多、負載過大,而其他RegionServer負載卻很小,這樣就造成熱點現象。大量訪問會使熱點Region所在的主機負載過大,引起性能下降,甚至導致Region不可用。所以我們在向HBase中插入數據的時候,應盡量均衡地把記錄分散到不同的Region里去,平衡每個Region的壓力。

下面根據一個例子分別介紹下根據RowKey進行查詢的時候支持的情況。

如果我們RowKey設計為uid+phone+name,那么這種設計可以很好的支持一下的場景:

uid=873969725 AND phone=18900000000 AND name=zhangsan
uid= 873969725 AND phone=18900000000
uid= 873969725 AND phone=189?
uid= 873969725

難以支持的場景:

phone=18900000000 AND name = zhangsan
phone=18900000000
name=zhangsan

從上面的例子中可以看出,在進行查詢的時候,根據RowKey從前向后匹配,所以我們在設計RowKey的時候選擇好字段之后,還應該結合我們的實際的高頻的查詢場景來組合選擇的字段,越高頻的查詢字段排列越靠左。

RowKey在Region中的作用

在 HBase 中,Region 相當於一個數據的分片,每個 Region 都有StartRowKeyStopRowKey,這是表示 Region 存儲的 RowKey 的范圍,HBase 表的數據時按照 RowKey 來分散到不同的 Region,要想將數據記錄均衡的分散到不同的Region中去,因此需要 RowKey 滿足這種散列的特點。此外,在數據讀寫過程中也是與RowKey 密切相關,RowKey在讀寫過程中的作用:

  1. 讀寫數據時通過 RowKey 找到對應的 Region;

  2. MemStore 中的數據是按照 RowKey 的字典序排序;

  3. HFile 中的數據是按照 RowKey 的字典序排序。

RowKey的設計

在HBase中RowKey在數據檢索和數據存儲方面都有重要的作用,一個好的RowKey設計會影響到數據在HBase中的分布,還會影響我們查詢效率,所以一個好的RowKey的設計方案是多么重要。首先我們先來了解下RowKey的設計原則。

RowKey設計原則

長度原則

RowKey是一個二進制碼流,可以是任意字符串,最大長度為64kb,實際應用中一般為10-100byte,以byte[]形式保存,一般設計成定長。建議越短越好,不要超過16個字節,原因如下:

  1. 數據的持久化文件HFile中時按照Key-Value存儲的,如果RowKey過長,例如超過100byte,那么1000w行的記錄,僅RowKey就需占用近1GB的空間。這樣會極大影響HFile的存儲效率。

  2. MemStore會緩存部分數據到內存中,若RowKey字段過長,內存的有效利用率就會降低,就不能緩存更多的數據,從而降低檢索效率。

  3. 目前操作系統都是64位系統,內存8字節對齊,控制在16字節,8字節的整數倍利用了操作系統的最佳特性。

唯一原則

必須在設計上保證RowKey的唯一性。由於在HBase中數據存儲是Key-Value形式,若向HBase中同一張表插入相同RowKey的數據,則原先存在的數據會被新的數據覆蓋。

排序原則

HBase的RowKey是按照ASCII有序排序的,因此我們在設計RowKey的時候要充分利用這點。

散列原則

設計的RowKey應均勻的分布在各個HBase節點上。

RowKey字段選擇

RowKey字段的選擇,遵循的最基本原則是唯一性,RowKey必須能夠唯一的識別一行數據。無論應用的負載特點是什么樣,RowKey字段都應該參考最高頻的查詢場景。數據庫通常都是以如何高效的讀取和消費數據為目的,而不是數據存儲本身。然后,結合具體的負載特點,再對選取的RowKey字段值進行改造,組合字段場景下需要重點考慮字段的順序。

避免數據熱點的方法

在對HBase的讀寫過程中,如何避免熱點現象呢?主要有以下幾種方法:

Reversing

如果經初步設計出的RowKey在數據分布上不均勻,但RowKey尾部的數據卻呈現出了良好的隨機性,此時,可以考慮將RowKey的信息翻轉,或者直接將尾部的bytes提前到RowKey的開頭。Reversing可以有效的使RowKey隨機分布,但是犧牲了RowKey的有序性。

缺點:

利於Get操作,但不利於Scan操作,因為數據在原RowKey上的自然順序已經被打亂。

Salting

Salting(加鹽)的原理是在原RowKey的前面添加固定長度的隨機數,也就是給RowKey分配一個隨機前綴使它和之間的RowKey的開頭不同。隨機數能保障數據在所有Regions間的負載均衡。

缺點:

因為添加的是隨機數,基於原RowKey查詢時無法知道隨機數是什么,那樣在查詢的時候就需要去各個可能的Regions中查找,Salting對於讀取是利空的。並且加鹽這種方式增加了讀寫時的吞吐量。

Hashing

基於 RowKey 的完整或部分數據進行 Hash,而后將Hashing后的值完整替換或部分替換原RowKey的前綴部分。這里說的 hash 包含 MD5、sha1、sha256 或 sha512 等算法。

缺點:

與 Reversing 類似,Hashing 也不利於 Scan,因為打亂了原RowKey的自然順序。

RowKey設計案例剖析

1. 查詢某用戶在某應用中的操作記錄

reverse(userid) + appid + timestamp

2. 查詢某用戶在某應用中的操作記錄(優先展現最近的數據)

reverse(userid) + appid + (Long.Max_Value - timestamp)

3. 查詢某用戶在某段時間內所有應用的操作記錄

reverse(userid) + timestamp + appid

4. 查詢某用戶的基本信息

reverse(userid)

5. 查詢某eventid記錄信息

salt + eventid + timestamp

如果 userid是按數字遞增的,並且長度不一,可以先預估 userid 最大長度,然后將userid進行翻轉,再在翻轉之后的字符串后面補0(至最大長度);如果長度固定,直接進行翻轉即可(如手機號碼)。

在第5個例子中,加鹽的目的是為了增加查詢的並發性,加入Slat的范圍是0~n,可以將數據分為n個split同時做scan操作,有利於提高查詢效率。

總結

在HBase的使用過程,設計RowKey是一個很重要的一個環節。我們在進行RowKey設計的時候可參照如下步驟:

  1. 結合業務場景特點,選擇合適的字段來做為RowKey,並且按照查詢頻次來放置字段順序

  2. 通過設計的RowKey能盡可能的將數據打散到整個集群中,均衡負載,避免熱點問題

  3. 設計的RowKey應盡量簡短


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM