使用HBase時(shí)間也不短了,看到周圍也有很多人逐步在應(yīng)用HBase臀规,于是打算總結(jié)一下HBase常見的坑者春,給新入坑的小伙伴的一些參考。
本篇為入門篇辉懒,以HBase的基礎(chǔ)概念為主阳惹,后期可能會(huì)引入項(xiàng)目中的實(shí)際應(yīng)用。
入坑前請(qǐng)細(xì)讀官方文檔耗帕,官方文檔,文檔……
重要的事情說三遍袱贮,哪怕只是快速掃一眼仿便,也請(qǐng)快速掃完官方文檔,再來詳讀本篇內(nèi)容攒巍。本篇內(nèi)容不會(huì)對(duì)HBase的各種好處以及詳細(xì)設(shè)計(jì)鼓吹一通嗽仪,只是快速總結(jié)下需要注意的點(diǎn)與可能遇到的坑。因此無論何時(shí)請(qǐng)務(wù)必以官方文檔為主柒莉。以下只是總結(jié)初次接觸時(shí)的一些要點(diǎn)闻坚,讀者默認(rèn)為是已經(jīng)了解HBase的場(chǎng)景及用途,如果還在糾結(jié)是否要用HBase的朋友兢孝,請(qǐng)先閱讀官方文檔了解設(shè)計(jì)窿凤,再?zèng)Q定是否切換到HBase吧。
HBase上手并不那么容易跨蟹,而且hbase shell命令行工具可能也不像其他RDBMS的cli界面那么好用雳殊,很多你習(xí)慣的功能可能沒有,甚至可能要非常復(fù)雜窗轩,這些請(qǐng)務(wù)必提前做好準(zhǔn)備夯秃。
另外,國(guó)內(nèi)中文資料大多版本停留在古老的0.94版本,大多數(shù)已經(jīng)不具有參考價(jià)值仓洼,請(qǐng)務(wù)必以官方文檔為準(zhǔn)介陶。
發(fā)行版的選擇
可能有些小伙伴已經(jīng)聽說過了Hadoop有各種發(fā)行版了,而HBase直接跑在Hadoop之上色建,所以也會(huì)有各種選擇哺呜。比如官方開源版本,Cloudera版本镀岛,MapR等等諸多發(fā)行版弦牡,一些選擇恐懼癥的小伙伴可能已經(jīng)要瘋了,入門都要糾結(jié)半天漂羊。
這里我不會(huì)費(fèi)力的去比對(duì)各種版本的異同驾锰,僅給出我個(gè)人的上手意見。初學(xué)以及本地快速搭建環(huán)境走越,推薦使用官方版本椭豫,因?yàn)橄鄬?duì)獲取容易,本地開發(fā)啟動(dòng)容易旨指,文檔資料較多赏酥。
如果是產(chǎn)品環(huán)境部署,我個(gè)人推薦使用Cloudera的CDH谆构,因?yàn)樗鼛в幸粋€(gè)圖形化的集群部署以及管理工具Cloudera Manager裸扶,產(chǎn)品環(huán)境部署升級(jí)維護(hù)都極其方便,以及相對(duì)更新比較平穩(wěn)搬素,性能比較穩(wěn)定呵晨。個(gè)人推薦使用Cloudera Manager部署三節(jié)點(diǎn)集群做產(chǎn)品環(huán)境。
NOTE: 可能有些人會(huì)問熬尺,我在本地使用官方版本的Hadoop摸屠,產(chǎn)品環(huán)境使用CDH,那么能兼容嗎粱哼?以我多年的實(shí)際使用經(jīng)驗(yàn)來看季二,是可以的,絕大多數(shù)使用不會(huì)遇到問題揭措。某些yarn的api可能會(huì)遇到CDH版本和官方版本不同胯舷,那么只需要加入Cloudera的maven倉(cāng)庫(kù),使用cloudera版本的jar包替換項(xiàng)目依賴即可绊含。
HBase的存儲(chǔ)
這個(gè)坑是很多入門的朋友最容易迷惑的需纳,詳細(xì)描述官方文檔都有,這里只總結(jié)一些要點(diǎn):
- HBase中的存儲(chǔ)
一切皆是字節(jié)
- HBase的RowKey會(huì)按照字節(jié)順序排序艺挪,并且添加索引
- HBase會(huì)按照row數(shù)量自動(dòng)切割成Region不翩,保持負(fù)載均衡與冗余(策略可改兵扬,如需調(diào)整默認(rèn)行為請(qǐng)?jiān)敿?xì)閱讀官方文檔)
在HBase,你存的任何內(nèi)容都必須轉(zhuǎn)為byte[]
字節(jié)流進(jìn)行存儲(chǔ)口蝠,在Java代碼中可以調(diào)用hbase-client
jar包中的org.apache.hadoop.hbase.util.Bytes.toBytes()
方法將各種基本類型的數(shù)據(jù)轉(zhuǎn)為byte[]
字節(jié)流器钟。所以解析數(shù)據(jù)的壓力就放在了客戶端∶钫幔客戶端從HBase拿到了字節(jié)流傲霸,進(jìn)行相應(yīng)的解碼算法還原為原始數(shù)據(jù)(比如通過org.apache.hadoop.hbase.util.Bytes.toInt()
將byte[]
還原回int)。因此要求存入數(shù)據(jù)之前用戶必須設(shè)計(jì)好存儲(chǔ)內(nèi)容——HBase根本不管你存入的是什么玩意眉反,對(duì)它來說就是一個(gè)byte[]
昙啄,用戶必須自己負(fù)責(zé)解析內(nèi)容,因此存儲(chǔ)數(shù)據(jù)之前必須想好你要存什么寸五,以及如何解析梳凛。這點(diǎn)和很多常見的RDB有很大的不同。
HBase的RowKey
天生自帶索引梳杏,并且按字節(jié)順序排列韧拒,而且天然分布式。因此設(shè)計(jì)RowKey
就成了用好HBase的關(guān)鍵十性。你可以把RowKey想象中SQL語句中SELECT col FROM htable WHERE (condition);
其中的condition
叛溢,用HBase之前務(wù)必先設(shè)計(jì)好你的查詢條件,將你的WHERE
條件的語句作為RowKey
存儲(chǔ)劲适。
HBase的存儲(chǔ)結(jié)構(gòu)
每個(gè)HBase的table存儲(chǔ)的結(jié)果大致如下表所示:
在qualifier
之上還有個(gè)層級(jí)column family
楷掉,相比傳統(tǒng)的RDB多了一個(gè)層級(jí),初次使用可能會(huì)不適應(yīng)霞势。一些概念解釋如下:
Term | Description |
---|---|
Row | HBase中的"行"烹植,包含一個(gè)row key(行鍵)和若干個(gè)column(列) |
Column Family | "列族",相當(dāng)于列的分組支示,由多個(gè)列構(gòu)成一個(gè)列族刊橘。同一列族下的列具有相同的屬性 |
Column Qualifier | 就是列族下某個(gè)具體的"列"鄙才,Qualifier的屬性受到Column Family限制 |
Column | "列"颂鸿,表示存儲(chǔ)中的某一具體的列,包含列族和Qualifier攒庵,用: 連接: cf:qualifier
|
Cell | 就是由行列所唯一確定的單元格嘴纺。一個(gè)單元格可能包含多個(gè)version |
Timestamp | 每個(gè)Cell中都會(huì)包含一個(gè)元數(shù)據(jù)Timestamp ,主要用于區(qū)分存儲(chǔ)的版本 |
特別注意HBase中每個(gè)單元格可以存儲(chǔ)多個(gè)Version
浓冒,但是通常不建議存儲(chǔ)多個(gè)Version
栽渴,Version
是通過Timestamp
屬性區(qū)分的。每個(gè)table中也不建議使用過多的Column Family
稳懒。
關(guān)于HBase Shell
首先要有一個(gè)了解闲擦,就是hbase shell
使用JRuby
開發(fā)的,這個(gè)命令行實(shí)際跑的是ruby
代碼,理論上你可以在這個(gè)Shell上跑任何Ruby代碼墅冷,而不要把自己局限在help
輸出的那幾個(gè)固定的函數(shù)纯路。
比如一個(gè)常用的例子,就是將hbase shell中輸出的各種hex string還原為對(duì)應(yīng)的數(shù)據(jù)類型寞忿,比如這樣scan 'table'
之后驰唬,經(jīng)常能看到類似于這樣的內(nèi)容:
\x00\x00\x00\x00\x00\x00\x00\x0 column=cf:\x00\x02\x98\x10, timestamp=1458266571188, value=xxxxxx
1\x7F\xFF\xFE\xACx\x8C\x9A\xFF
1 row(s) in 0.1930 seconds
我們已知我們存儲(chǔ)的結(jié)構(gòu)是RowKey
存儲(chǔ)結(jié)構(gòu)是long-long
共16個(gè)字節(jié), column的存儲(chǔ)結(jié)構(gòu)是cf:int
,int占4個(gè)字節(jié)腔彰,那么我們可以在終端下使用ruby代碼直接還原出這個(gè)hex string:
hbase(main):003:0> "\x00\x00\x00\x00\x00\x00\x00\x01".unpack("N")
=> [0]
hbase(main):004:0> "\x7F\xFF\xFE\xACx\x8C\x9A\xFF".unpack("N")
=> [2147483308]
hbase(main):005:0> "\x00\x02\x98\x10".unpack("N")
=> [170000]
直接使用ruby的unpack方法叫编,將hex string還原為對(duì)應(yīng)的long
和int
,得知我們到底存儲(chǔ)的是什么玩意霹抛。如果熟悉一點(diǎn)ruby代碼的話搓逾,用hbase shell會(huì)得心應(yīng)手。即使不了解上炎,也可以通過搜索引擎幫我們找到合適的ruby代碼放到hbase shell中使用恃逻。
一些常見的表結(jié)構(gòu)設(shè)計(jì)套路
在官方文檔中已經(jīng)羅列了一些常見的HBase場(chǎng)景中結(jié)構(gòu)設(shè)計(jì)的套路,可以參考藕施。尤其是做時(shí)序數(shù)據(jù)庫(kù)的時(shí)候寇损,那么OpenTSDB
的表結(jié)構(gòu)值得參考。
后續(xù)會(huì)逐步總結(jié)下我們?cè)趯?shí)戰(zhàn)中的一些篩選查詢范例以供參考裳食。