Hbase rowkey設計

hbase的rowkey設計決定了數據的分區和查詢的方式,是使用hbase前一定要想清楚的,以下簡單列舉了設計hbase rowkey時需要考慮的問題

1. rowkey是唯一的嗎?

rowkey相同的記錄在hbase裏被認爲是同一條數據的多個版本,查詢時默認返回最新版本的數據,所以通常rowkey都需要保證唯一,除非用到多版本特性

最佳設計實踐:

rowkey就好比數據庫的裏的主鍵,他唯一確定了一條記錄,它可以是一個字段也可以是多個字段拼接起來:

每個用戶只有一條記錄: [userid]

每個用戶有多條交易記錄:[userid][orderid]

2. 滿足查詢場景嗎?

rowkey的設計限制了數據的查詢方式,hbase只有兩種查詢方式:

1. 根據完整的rowkey查詢(get)

類似傳統DB的sql:

select * from table where rowkey = ‘abcde’

這種查詢方式需要知道完整的rowkey,即組成rowkey的所有字段的值都是確定的

2. 根據rowkey的範圍查詢(scan):

類似傳統DB的sql:

select * from table where ‘abc’ < rowkey <’abcx’

這種查詢方式需要知道數據rowkey左邊的值,就好像一本英文字典,你可以查詢pre開頭的所有單詞,也可以查詢prefi開頭的所有單詞,但是沒辦法查詢中間是efi或結尾是ix的所有單詞,除非翻閱整個字典

最佳設計實踐:

在有限的查詢方式下如何實現複雜查詢:

1.再建另外一張表作爲索引表,應用雙寫

2.使用filter,在服務端過濾掉不需要的數據

3.使用二級索引

4.如何實現倒序(新的數據排在前面,如:order by orderTime desc):

  使用反向scan:scan.setReverse(true)

  #反向scan的性能比正常scan要差,如果倒序的場景佔大頭可以設計上就把數據倒序:

  [hostname][log-event][timestamp]  => [hostname][log-event][Long.MAX_VALUE – timestamp]

3. 數據足夠分散,會產生熱點嗎?

散列的目的是數據可以分散到不同的分區,不至於產生熱點,把某一臺服務器累死,其他服務器閒置,充分發揮分佈式和併發的優勢

最佳設計實踐:

1.md5

  [userId][orderid]  =>  [md5(userid).subStr(0,4)][userId][orderid]

2.反轉

  [userId][orderid] => [reverse(userid)][orderid]

3.取模

  [timestamp][hostname][log-event]  => [bucket][timestamp][hostname][log-event]

  long bucket = timestamp % numBuckets;

4.增加隨機數

  [userId][orderid] => [userId][orderid][random(100)]

4. rowkey可以再短點嗎?

短的rowkey可以減少數據量 ,提高查詢寫入性能

最佳設計實踐:

1. 使用long或int型代替String

  如: '2015122410' => Long(2015122410)

2. 使用編碼代替名稱

  如:’淘寶‘ => tb

5. scan時會不會查詢出不需要的數據?

假設有以下場景:

table1的rowkey是: colume1+ colume2+ colume3

現在需要查詢colume1= host1 的所有數據:

scan 'table1',{startkey=> 'host1',endkey=> 'host2'}

此時如果有一條記錄colume1=host12,這條記錄也會被查詢出來:因爲:

'host1' < 'host12' < 'host2'

但顯然這條記錄不是我們想要的

最佳設計實踐:

1. 字段定長

  [colume1][colume2] => [rpad(colume1,'x',20)][colume2]

2. 添加分隔符

  [colume1][colume2] => [colume1][_][colume2]

常見設計實例:

日誌類、時間序列數據

查詢場景:

1.查詢某臺機器某個指標某段時間內的數據

[hostname][log-event][timestamp]

2.查詢某臺機器某個指標最新的幾條數據

timestamp = Long.MAX_VALUE – timestamp

[hostname][log-event][timestamp]

3.數據只有時間一個維度或某一個維度數據量特別大

long bucket = timestamp % numBuckets;

[bucket][timestamp][hostname][log-event]

交易類數據

查詢場景:

1.查詢某個賣家某段時間內的交易記錄

[seller id][timestmap][order number]

2.查詢某個買家某段時間內的交易記錄

[buyer id][timestmap][order number]

3.根據訂單號查詢

[order number]

4.同時滿足1,2,3

三張表:

一張買家維度表,rowkey爲:

[buyer id][timestmap][order number]

一張賣家維度表,rowkey爲:

[seller id][timestmap][order number]

一張訂單索引表,rowkey爲:

[order number]

文章來源:https://www.jianshu.com/p/e115189001fe

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章