HBase入坑須知(一)

使用HBase時間也不短了,看到周圍也有很多人逐步在應用HBase,于是打算總結一下HBase常見的坑,給新入坑的小伙伴的一些參考。

本篇為入門篇,以HBase的基礎概念為主,后期可能會引入項目中的實際應用。

入坑前請細讀官方文檔,官方文檔,文檔……

重要的事情說三遍,哪怕只是快速掃一眼,也請快速掃完官方文檔,再來詳讀本篇內容。本篇內容不會對HBase的各種好處以及詳細設計鼓吹一通,只是快速總結下需要注意的點與可能遇到的坑。因此無論何時請務必以官方文檔為主。以下只是總結初次接觸時的一些要點,讀者默認為是已經了解HBase的場景及用途,如果還在糾結是否要用HBase的朋友,請先閱讀官方文檔了解設計,再決定是否切換到HBase吧。

HBase上手并不那么容易,而且hbase shell命令行工具可能也不像其他RDBMS的cli界面那么好用,很多你習慣的功能可能沒有,甚至可能要非常復雜,這些請務必提前做好準備。

另外,國內中文資料大多版本停留在古老的0.94版本,大多數(shù)已經不具有參考價值,請務必以官方文檔為準。

發(fā)行版的選擇

可能有些小伙伴已經聽說過了Hadoop有各種發(fā)行版了,而HBase直接跑在Hadoop之上,所以也會有各種選擇。比如官方開源版本,Cloudera版本,MapR等等諸多發(fā)行版,一些選擇恐懼癥的小伙伴可能已經要瘋了,入門都要糾結半天。

這里我不會費力的去比對各種版本的異同,僅給出我個人的上手意見。初學以及本地快速搭建環(huán)境,推薦使用官方版本,因為相對獲取容易,本地開發(fā)啟動容易,文檔資料較多。

如果是產品環(huán)境部署,我個人推薦使用Cloudera的CDH,因為它帶有一個圖形化的集群部署以及管理工具Cloudera Manager,產品環(huán)境部署升級維護都極其方便,以及相對更新比較平穩(wěn),性能比較穩(wěn)定。個人推薦使用Cloudera Manager部署三節(jié)點集群做產品環(huán)境。

NOTE: 可能有些人會問,我在本地使用官方版本的Hadoop,產品環(huán)境使用CDH,那么能兼容嗎?以我多年的實際使用經驗來看,是可以的,絕大多數(shù)使用不會遇到問題。某些yarn的api可能會遇到CDH版本和官方版本不同,那么只需要加入Cloudera的maven倉庫,使用cloudera版本的jar包替換項目依賴即可。

HBase的存儲

這個坑是很多入門的朋友最容易迷惑的,詳細描述官方文檔都有,這里只總結一些要點:

  • HBase中的存儲一切皆是字節(jié)
  • HBase的RowKey會按照字節(jié)順序排序,并且添加索引
  • HBase會按照row數(shù)量自動切割成Region,保持負載均衡與冗余(策略可改,如需調整默認行為請詳細閱讀官方文檔)

在HBase,你存的任何內容都必須轉為byte[]字節(jié)流進行存儲,在Java代碼中可以調用hbase-client jar包中的org.apache.hadoop.hbase.util.Bytes.toBytes()方法將各種基本類型的數(shù)據(jù)轉為byte[]字節(jié)流。所以解析數(shù)據(jù)的壓力就放在了客戶端。客戶端從HBase拿到了字節(jié)流,進行相應的解碼算法還原為原始數(shù)據(jù)(比如通過org.apache.hadoop.hbase.util.Bytes.toInt()byte[]還原回int)。因此要求存入數(shù)據(jù)之前用戶必須設計好存儲內容——HBase根本不管你存入的是什么玩意,對它來說就是一個byte[],用戶必須自己負責解析內容,因此存儲數(shù)據(jù)之前必須想好你要存什么,以及如何解析。這點和很多常見的RDB有很大的不同。

HBase的RowKey天生自帶索引,并且按字節(jié)順序排列,而且天然分布式。因此設計RowKey就成了用好HBase的關鍵。你可以把RowKey想象中SQL語句中SELECT col FROM htable WHERE (condition);其中的condition,用HBase之前務必先設計好你的查詢條件,將你的WHERE條件的語句作為RowKey存儲。

HBase的存儲結構

每個HBase的table存儲的結果大致如下表所示:

image.png

qualifier之上還有個層級column family,相比傳統(tǒng)的RDB多了一個層級,初次使用可能會不適應。一些概念解釋如下:

Term Description
Row HBase中的"行",包含一個row key(行鍵)和若干個column(列)
Column Family "列族",相當于列的分組,由多個列構成一個列族。同一列族下的列具有相同的屬性
Column Qualifier 就是列族下某個具體的"列",Qualifier的屬性受到Column Family限制
Column "列",表示存儲中的某一具體的列,包含列族和Qualifier,用:連接: cf:qualifier
Cell 就是由行列所唯一確定的單元格。一個單元格可能包含多個version
Timestamp 每個Cell中都會包含一個元數(shù)據(jù)Timestamp,主要用于區(qū)分存儲的版本

特別注意HBase中每個單元格可以存儲多個Version,但是通常不建議存儲多個Version,Version是通過Timestamp屬性區(qū)分的。每個table中也不建議使用過多的Column Family。

關于HBase Shell

首先要有一個了解,就是hbase shell使用JRuby開發(fā)的,這個命令行實際跑的是ruby代碼,理論上你可以在這個Shell上跑任何Ruby代碼,而不要把自己局限在help輸出的那幾個固定的函數(shù)。

比如一個常用的例子,就是將hbase shell中輸出的各種hex string還原為對應的數(shù)據(jù)類型,比如這樣scan 'table'之后,經常能看到類似于這樣的內容:

 \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

我們已知我們存儲的結構是RowKey存儲結構是long-long共16個字節(jié), column的存儲結構是cf:int,int占4個字節(jié),那么我們可以在終端下使用ruby代碼直接還原出這個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還原為對應的longint,得知我們到底存儲的是什么玩意。如果熟悉一點ruby代碼的話,用hbase shell會得心應手。即使不了解,也可以通過搜索引擎幫我們找到合適的ruby代碼放到hbase shell中使用。

一些常見的表結構設計套路

官方文檔中已經羅列了一些常見的HBase場景中結構設計的套路,可以參考。尤其是做時序數(shù)據(jù)庫的時候,那么OpenTSDB表結構值得參考。

后續(xù)會逐步總結下我們在實戰(zhàn)中的一些篩選查詢范例以供參考。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容