1. 程式人生 > >HBase之Rowkey設計總結及易觀方舟實戰篇

HBase之Rowkey設計總結及易觀方舟實戰篇

 

置頂 2018年06月02日 21:52:46 代立冬 閱讀數:1699 標籤:  Rowkey設計經驗hbase經驗總結易觀方舟rowkey設計實踐rowkey實戰 更多

個人分類: ●HBase--------【HBase優化】

所屬專欄: 大資料實戰系列

版權宣告:*************本文為博主原創文章,轉載請註明出處************* https://blog.csdn.net/oDaiLiDong/article/details/80551851

一、引言

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加鹽

Salt是將每一個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碼錶

ASCII值

字元

ASCII值

字元

ASCII值

字元

32

(space)

64

@

96

33

!

65

A

97

a

34

"

66

B

98

b

35

#

67

C

99

c

36

$

68

D

100

d

37

%

69

E

101

e

38

&

70

F

102

f

39

,

71

G

103

g

40

(

72

H

104

h

41

)

73

I

105

i

42

*

74

J

106

j

43

+

75

K

107

k

44

,

76

L

108

l

45

-

77

M

109

m

46

.

78

N

110

n

47

/

79

O

111

o

48

0

80

P

112

p

49

1

81

Q

113

q

50

2

82

R

114

r

51

3

83

S

115

s

52

4

84

T

116

t

53

5

85

U

117

u

54

6

86

V

118

v

55

7

87

W

119

w

56

8

88

X

120

x

57

9

89

Y

121

y

58

:

90

Z

122

z

59

;

91

[

123

{

60

<

92

/

124

|

61

=

93

]

125

}

62

>

94

^

126

`

63

?

95

_