硬核技術分析帖:HBase之Rowkey設計總結及易觀方舟實戰篇

硬核技術分析帖:HBase之Rowkey設計總結及易觀方舟實戰篇

導讀

HBase是一個分佈式的、面向列的開源數據庫,不同於一般的關係數據庫,它是一個適合於非結構化數據存儲的數據庫;此外,HBase根據Rowkey進行檢索。本篇文章則將圍繞Rowkey的設計原則,以及結合易觀方舟實際案例,進行立體式分析解讀。

一、引言

HBase由於其存儲和讀寫的高性能,在OLAP即時分析中越來越發揮重要的作用,在易觀精細化運營產品--易觀方舟也有廣泛的應用。作為Nosql數據庫的一員,HBase查詢只能通過其Rowkey來查詢(Rowkey用來表示唯一一行記錄),Rowkey設計的優劣直接影響讀寫性能。HBase中的數據是按照Rowkey的ASCII字典順序進行全局排序的,有夥伴可能對ASCII字典序印象不夠深刻,下面舉例說明:

假如有5個Rowkey:"012", "0", "123", "234", "3",按ASCII字典排序後的結果為:"0", "012", "123", "234", "3"。(注:文末附常用ASCII碼錶)

Rowkey排序時會先比對兩個Rowkey的第一個字節,如果相同,然後會比對第二個字節,依次類推... 對比到第X個字節時,已經超出了其中一個Rowkey的長度,短的Rowkey排在前面。

由於HBase是通過Rowkey查詢的,一般Rowkey上都會存一些比較關鍵的檢索信息,我們需要提前想好數據具體需要如何查詢,根據查詢方式進行數據存儲格式的設計,要避免做全表掃描,因為效率特別低。

二、Rowkey設計原則

Rowkey設計應遵循以下原則:

1.Rowkey的唯一原則

必須在設計上保證其唯一性。由於在HBase中數據存儲是Key-Value形式,若HBase中同一表插入相同Rowkey,則原先的數據會被覆蓋掉(如果表的version設置為1的話),所以務必保證Rowkey的唯一性。

2. Rowkey的排序原則

HBase的Rowkey是按照ASCII有序設計的,我們在設計Rowkey時要充分利用這點。比如視頻網站上對影片《泰坦尼克號》的彈幕信息,這個彈幕是按照時間倒排序展示視頻裡,這個時候我們設計的Rowkey要和時間順序相關。可以使用"Long.MAX_VALUE - 彈幕發表時間"的long 值作為Rowkey 的前綴。

3. Rowkey的散列原則

我們設計的Rowkey應均勻的分佈在各個HBase節點上。拿常見的時間戳舉例,假如Rowkey是按系統時間戳的方式遞增,Rowkey的第一部分如果是時間戳信息的話將造成所有新數據都在一個RegionServer上堆積的熱點現象,也就是通常說的Region熱點問題, 熱點發生在大量的client直接訪問集中在個別RegionServer上(訪問可能是讀,寫或者其他操作),導致單個RegionServer機器自身負載過高,引起性能下降甚至Region不可用,常見的是發生jvm full gc或者顯示region too busy異常情況,當然這也會影響同一個RegionServer上的其他Region。

通常有3種辦法來解決這個Region熱點問題:

ΩΩ1、Reverse反轉

針對固定長度的Rowkey反轉後存儲,這樣可以使Rowkey中經常改變的部分放在最前面,可以有效的隨機Rowkey。

反轉Rowkey的例子通常以手機舉例,可以將手機號反轉後的字符串作為Rowkey,這樣的就避免了以手機號那樣比較固定開頭(137x、15x等)導致熱點問題,

這樣做的缺點是犧牲了Rowkey的有序性。

ΩΩ2、Salt加鹽

Salting是將每一個Rowkey加一個前綴,前綴使用一些隨機字符,使得數據分散在多個不同的Region,達到Region負載均衡的目標。

比如在一個有4個Region(注:以[ ,a)、[a,b)、[b,c)、[c, )為Region起至)的HBase表中,加Salt前的Rowkey:abc001、abc002、abc003

我們分別加上a、b、c前綴,加Salt後Rowkey為:a-abc001、b-abc002、c-abc003

可以看到,加鹽前的Rowkey默認會在第2個region中,加鹽後的Rowkey數據會分佈在3個region中,理論上處理後的吞吐量應是之前的3倍。由於前綴是隨機的,讀這些數據時需要耗費更多的時間,所以Salt增加了寫操作的吞吐量,不過缺點是同時增加了讀操作的開銷。

ΩΩ3、Hash散列或者Mod

用Hash散列來替代隨機Salt前綴的好處是能讓一個給定的行有相同的前綴,這在分散了Region負載的同時,使讀操作也能夠推斷。確定性Hash(比如md5後取前4位做前綴)能讓客戶端重建完整的RowKey,可以使用get操作直接get想要的行。

例如將上述的原始Rowkey經過hash處理,此處我們採用md5散列算法取前4位做前綴,結果如下:

9bf0-abc001(abc001在md5後是9bf049097142c168c38a94c626eddf3d,取前4位是9bf0)

7006-abc002

95e6-abc003

若以前4個字符作為不同分區的起止,上面幾個Rowkey數據會分佈在3個region中。實際應用場景是當數據量越來越大的時候,這種設計會使得分區之間更加均衡。

如果Rowkey是數字類型的,也可以考慮Mod方法。

4. Rowkey的長度原則

Rowkey長度設計原則:Rowkey是一個二進制,Rowkey的長度被很多開發者建議說設計在10~100個字節,建議是越短越好。

原因有兩點:

其一是HBase的持久化文件HFile是按照KeyValue存儲的,如果Rowkey過長比如500個字節,1000萬列數據光Rowkey就要佔用500*1000萬=50億個字節,將近1G數據,這會極大影響HFile的存儲效率

其二是MemStore緩存部分數據到內存,如果Rowkey字段過長內存的有效利用率會降低,系統無法緩存更多的數據,這會降低檢索效率

需要指出的是不僅Rowkey的長度是越短越好,而且列族名、列名等儘量使用短名字,因為HBase屬於列式數據庫,這些名字都是會寫入到HBase的持久化文件HFile中去,過長的Rowkey、列族、列名都會導致整體的存儲量成倍增加。

三、方舟HBase Rowkey設計實戰

在實際的設計中我們可能更多的是結合多種設計方法來實現Rowkey的最優化設計,比如設計訂單狀態表時使用:Rowkey: reverse(order_id) + (Long.MAX_VALUE – timestamp),這樣設計的好處一是通過reverse訂單號避免Region熱點,二是可以按時間倒排顯示。

結合易觀方舟使用HBase作為事件(事件指的的終端在APP中發生的行為,比如登錄、下單等等統稱事件(event))的臨時存儲(HBase只存儲了最近10分鐘的熱數據)來舉例:

設計event事件的Rowkey為:兩位隨機數Salt + eventId + Date + kafka的Offset

這樣設計的好處是:

設計加鹽的目的是為了增加查詢的併發性,假如Salt的範圍是0~n,那我們在查詢的時候,可以將數據分為n個split同時做scan操作。經過我們的多次測試驗證,增加併發度能夠將整體的查詢速度提升5~20倍以上。隨後的eventId和Date是用來做範圍Scan使用的。在我們的查詢場景中,大部分都是指定了eventId的,因此我們把eventId放在了第二個位置上,同時呢,eventId的取值有幾十個,通過Salt + eventId的方式可以保證不會形成熱點。在單機部署版本中,HBase會存儲所有的event數據,所以我們把date放在rowkey的第三個位置上以實現按date做scan,批量Scan性能甚至可以做到毫秒級返回。

這樣的rowkey設計能夠很好的支持如下幾個查詢場景:

1、全表scan

在這種情況下,我們仍然可以將全表數據切分成n份併發查詢,從而實現查詢的實時響應。

2、只按照event_id查詢

3、按照event_id和date查詢

此外易觀方舟也使用HBase做用戶畫像的標籤存儲方案,存儲每個app的用戶的人口學屬性和商業屬性等標籤信息,由於其設計的更為複雜,後續會另起篇幅詳細展開。

最後我們順帶提下HBase的表設計,HBase表設計通常可以是寬表(wide table)模式,即一行包括很多列。同樣的信息也可以用高表(tall table)形式存儲,通常高表的性能比寬表要高出50%以上,所以推薦大家使用高表來完成表設計。表設計時,我們也應該要考慮HBase數據庫的一些特性:

(1)在HBase表中是通過Rowkey的字典序來進行數據排序的

(2)所有存儲在HBase表中的數據都是二進制的字節

(3)原子性只在行內保證,HBase不支持跨行事務

(4)列族(Column Family)在表創建之前就要定義好

(5)列族中的列標識(Column Qualifier)可以在表創建完以後動態插入數據時添加

四、總結

在做Rowkey設計時,請先考慮業務是讀比寫多、還是讀比寫少,HBase本身是為寫優化的,即便是這樣,也可能會出現熱點問題,而如果我們讀比較多的話,除了考慮以上Rowkey設計原則外,還可以考慮HBase的Coprocessor甚至elastic search結合的方法,無論哪種方式,都建議做實際業務場景下數據的壓力測試以得到最優結果。

附:常用ASCII碼錶

硬核技術分析帖:HBase之Rowkey設計總結及易觀方舟實戰篇

想看更多,請移步Analysys易觀(ID:enfodesk)微信公眾號。


分享到:


相關文章: