本文是對Hbase組件的一個學(xué)習(xí)總結(jié)饵隙,共包括如下章節(jié)的內(nèi)容:
- Hbase是什么
- Hbase的數(shù)據(jù)模型
- Hbase體系結(jié)構(gòu)
- 安裝和運行Hbase
- Hbase命令行
參考資料:
1簇捍、如果Hbase的數(shù)據(jù)要保存到hdfs上(一般生產(chǎn)環(huán)境下如此)填具,需要確保有可用的hadoop運行環(huán)境绍刮,可參見《Hadoop運行環(huán)境搭建》一文。
2魂贬、因為Hbase運行依賴zookeeper服務(wù)甫窟,Hbase本身內(nèi)置了zookeeper程序(往往用于開發(fā)和測試環(huán)境),如果希望獨立部署zookeeper服務(wù)(一般生產(chǎn)環(huán)境下如此)种冬,可參見《Zookeeper學(xué)習(xí)筆記》一文镣丑。
一、Hbase是什么
HBase是Google Bigtable的克隆版娱两。它是一個針對結(jié)構(gòu)化數(shù)據(jù)的可伸縮莺匠、高可靠、高性能十兢、分布式和面向列的動態(tài)模式數(shù)據(jù)庫趣竣。和傳統(tǒng)關(guān)系數(shù)據(jù)庫不同,HBase采用了BigTable的數(shù)據(jù)模型:增強的稀疏排序映射表(Key/Value)旱物,其中遥缕,鍵由行關(guān)鍵字、列關(guān)鍵字和時間戳構(gòu)成宵呛。HBase提供了對大規(guī)模數(shù)據(jù)的隨機通砍、實時讀寫訪問,同時,HBase中保存的數(shù)據(jù)可以使用MapReduce來處理封孙,它將數(shù)據(jù)存儲和并行計算完美地結(jié)合在一起迹冤。
二、Hbase的數(shù)據(jù)模型
Hbase的數(shù)據(jù)邏輯上是存儲在一張張表中虎忌。Hbase的表由行和列組成泡徙,行和列的交叉就是單元格,數(shù)據(jù)是存在單元格中的膜蠢,單元格是有版本的堪藐,即一個單元格可存儲多個版本的數(shù)據(jù)。
有幾個重要的概念:
1挑围、行鍵:
Hbase表的每行都有一個行浇妇骸(類似關(guān)系表的主鍵),表中的行按照行鍵進行排序杉辙,對表中行的訪問也是依據(jù)行健來訪問的模捂。
2、列族
行中的列被分成“列族”(column family)蜘矢。同一個列族的所有成員(即列)具有相同的前綴狂男。
表的列族是表模式的一部分,需要預(yù)先定義品腹。但是列不是表模式的一部分岖食。只要列族存在,客戶端可以在更新時提供新的列舞吭,并存儲它的值泡垃。
列名都以列族作為前綴,例如courses:history 羡鸥, courses:math 都屬于 courses 這個列族蔑穴。
這點與關(guān)系表不一樣,關(guān)系表的列是表模式的一部分兄春,關(guān)系表沒有列族的概念澎剥。對于關(guān)系表锡溯,每行數(shù)據(jù)都有相同的列赶舆。但對于hbase表,每行數(shù)據(jù)都有相同的列族祭饭,但不一定有相同的列芜茵。
3、時間戳
HBase中通過行鍵和列確定的一個存貯單元稱為單元格(cell)倡蝙。每個 cell都保存著同一份數(shù)據(jù)的多個版本九串。默認情況下,版本通過時間戳來索引。時間戳的類型是 64位整型猪钮。時間戳可以由HBase (在數(shù)據(jù)寫入時 )自動賦值品山,此時時間戳是精確到毫秒的當(dāng)前系統(tǒng)時間。時間戳也可以由客戶顯式賦值烤低。如果應(yīng)用程序要避免數(shù)據(jù)版本沖突肘交,就必須自己生成具有唯一性的時間戳。每個 cell中扑馁,不同版本的數(shù)據(jù)按照時間倒序排序涯呻,即最新的數(shù)據(jù)排在最前面。
為了避免數(shù)據(jù)存在過多版本造成的的管理 (包括存貯和索引)負擔(dān)腻要,HBase提供了兩種數(shù)據(jù)版本回收方式复罐。一是保存數(shù)據(jù)的最后n個版本,二是保存最近一段時間內(nèi)的版本(比如最近七天)雄家。用戶可以針對每個列族進行設(shè)置效诅。
說明:創(chuàng)建表時,默認情況下咳短,每個列族只支持存儲一個版本的數(shù)據(jù)填帽。這個可以通過alter語句來更改。
4咙好、單元(cell)
一個單元由{row key, column( =<family> + <label>), version} 唯一確定篡腌。cell中的數(shù)據(jù)是沒有類型的,全部是字節(jié)碼形式存儲勾效。
下面我們看一個例子嘹悼。
假設(shè)有一張Hbase表,表名為webtable层宫,該表有名為 contents杨伙、anchor 和 people 的三個列族。該表有兩行數(shù)據(jù)萌腿,行健分別為cn 和 en限匣。
對于第一行(cnn ),contents 列族包含一列(contents:html)毁菱,anchor 包含兩列(anchor:a米死,anchor:b),且第一行有5個版本贮庞。對于第二行(example)峦筒,只有1個版本,contents 列族包含一列(contents:html)窗慎,people列族包含一列(people:author)物喷。
表中有些數(shù)據(jù)卤材,下面通過表格的方式來展示下該表的數(shù)據(jù)。
此表中顯示為空的單元格在 HBase 中不占用空間或?qū)嶋H上存在峦失。這正是使 HBase “稀疏”的原因扇丛。表格視圖并不是查看 HBase 數(shù)據(jù)的唯一可能的方法,對于 “稀疏”表尉辑,采用表格視圖有時反而不是很方便晕拆。下面以類似json格式的視圖來展示上面數(shù)據(jù)。
{
"cn": {
contents: {
t6: contents:html: "內(nèi)容"
t5: contents:html: "內(nèi)容"
t3: contents:html: "內(nèi)容"
}
anchor: {
t9: anchor:a = "x"
t8: anchor:b = "y"
}
people: {}
}
"en": {
contents: {
t5: contents:html: "內(nèi)容"
}
anchor: {}
people: {
t5: people:author: "tom"
}
}
}
對于Hbase表材蹬,可以看作是key/value集合的nosql數(shù)據(jù)庫实幕,其中的key就是行鍵,value是一個單元格(cell)的列表堤器,單元格通過“列族+列+版本”來唯一標(biāo)識昆庇。
三、Hbase的物理存儲結(jié)構(gòu)
Hbase表中的所有行都按照行鍵的字典序排列闸溃,表在行的方向上分割為多個HRegion整吆。如下圖所示。
HRegion按大小分割辉川。每一個表一開始只有一個HRegion表蝙,隨著數(shù)據(jù)不斷插入表,HRegion不斷增大乓旗,當(dāng)增大到一定閾值的時候府蛇,HRegion就會等分為兩個新的HRegion。當(dāng)表中的行不斷增多屿愚,就會有越來越多的HRegion汇跨。
HRegion是HBase中分布式存儲和負載均衡的最小單元。最小單元就表示不同的HRegion可以分布在不同的HRegion Server上妆距。但是一個HRegion是不會拆分到多個HRegion Server上穷遂。
HRegion雖然是分布式存儲的最小單元,但并不是存儲的最小單元娱据。事實上蚪黑,HRegion由一個或者多個Store組成,每一個Store都保存一個列族中剩。每一個Store又由一個memStore和多個StoreFile組成忌穿。StoreFile以HFile格式保存在HDFS上。如下圖所示咽安。
memStore位于HRegion Server的內(nèi)存中伴网,數(shù)據(jù)寫入時蓬推,首先會寫入到memStore中妆棒,然后當(dāng)?shù)竭_一定的閥值的時候,Memstore中的數(shù)據(jù)會被刷到HFile中。
四糕珊、Hbase體系結(jié)構(gòu)
Hbase的架構(gòu)與hdfs,yarn類似动分,采用主從的架構(gòu),即一個Hbase系統(tǒng)包含一個master服務(wù)红选,若干個regionserver服務(wù)(分布在集群不同的機器上)澜公。另外因為Hbase依賴zookeeper,所以一個Hbase系統(tǒng)中還需要包含zookeeper服務(wù)(相對zookeeper服務(wù)來說喇肋,Hbase服務(wù)是zookeeper的客戶端)坟乾。當(dāng)然還有Hbase的客戶端(終端用戶或其它系統(tǒng)訪問Hbase服務(wù)的界面)。
下圖是Hbase集群系統(tǒng)的體系結(jié)構(gòu)示意圖蝶防。
因為Hbase的主節(jié)點master只有一個甚侣,存在單點故障風(fēng)險。在實際的環(huán)境下间学,往往會給mater節(jié)點配置HA殷费。
五、安裝和運行Hbase
安裝
1低葫、下載Hbase安裝壓縮包详羡,本文下載的是hbase-2.0.2-bin.tar.gz
2、解壓到某個目錄下嘿悬,我們這里解壓的位置是:
/home/hadoop/hbase2.0.2
3实柠、修改hadoop用戶的profile文件,設(shè)置環(huán)境變量
export HBASE_HOME=/home/hadoop/hbase-2.0.2
PATH=$PATH:$HBASE_HOME/bin
說明:Hbase的運行依賴java環(huán)境善涨,需要確保安裝運行Hbase的機器上有正持鞯剑可用的java環(huán)境。
Hbase有三種運行模式:獨立模式躯概;偽分布式模式登钥;分布式模式。下面分別介紹娶靡。
(一)獨立模式
獨立模式下牧牢,HBase系統(tǒng)的所有服務(wù)程序,Master姿锭、RegionServers 以及依賴的ZooKeeper服務(wù)都運行在一個jvm進程中塔鳍,Hbase不依賴hdfs,其數(shù)據(jù)存在本地文件中呻此。該模式轮纫,只能用于開發(fā)和測試環(huán)境,不能用于生產(chǎn)環(huán)境焚鲜。
獨立模式下掌唾,如果不修改Hbase的配置文件放前,Hbase和zookeeper數(shù)據(jù)會默認存儲到本地的/tmp/hbase-當(dāng)前用戶名 目錄下。但是如果所運行的機器上配置了hadoop環(huán)境糯彬,Hbase還是會去連接hdfs(這樣如果Hadoop未啟動凭语,會報錯)。所以最好能顯示的進行配置撩扒。
這時修改Hbase安裝目錄下conf目錄下的hbase-site.xml文件似扔,配置文件的內(nèi)容設(shè)置如下:
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///home/hadoop/hbasedata/hbase</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/hadoop/hbasedata/zk</value>
</property>
</configuration>
配置文件中的habse.rootdir屬性設(shè)置的是Hbase數(shù)據(jù)在本地的存儲目錄(使用本地磁盤存儲,需要加file://前綴)搓谆;habse.zookeeper.property.dataDir屬性設(shè)置的是zookeeper數(shù)據(jù)的存儲目錄(因為zk的數(shù)據(jù)本身就是存儲在本地炒辉,所以不用加file://前綴)。
然后在控制臺運行 start-hbase.sh 腳本就可以啟動Hbase服務(wù)泉手,這時我們用jps命令去查看辆脸,可以看到有一個名稱為HMaster的java進程(即包含hbase master,regionserver,zookeeper三個服務(wù)的合一進程)。如:
[hadoop@localhost ~]$ jps
......
24060 HMaster
.......
說明獨立模式下的Hbase服務(wù)啟動成功螃诅。
停止Hbase服務(wù)可以執(zhí)行 stop-hbase.sh腳本啡氢。
實際上,在獨立模式下术裸,Hbase的數(shù)據(jù)也可以不存儲在本地倘是,而是存儲到hdfs上,這時配置文件配置如下:
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://namenode地址:8020/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>false</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/hadoop/hbasedata/zk</value>
</property>
</configuration>
這種情況下袭艺,Hbase的各服務(wù)(包括zk服務(wù))依然運行在同一個jvm進程中搀崭。只是Hbase的數(shù)據(jù)存儲到hdfs文件系統(tǒng)中。配置文件中的hbase.rootdir屬性的值是一個hdfs系統(tǒng)的目錄猾编。當(dāng)然瘤睹,這種情況下,要Hbase服務(wù)能正常運行答倡,相應(yīng)的hdfs服務(wù)得正澈浯可用。
(二)偽分布式模式
這類似hadoop的偽分布式模式瘪撇,所有的Hbase服務(wù)以多個進程的方式運行获茬,但是運行在一臺機器上。這種模式一樣只適合開發(fā)和測試倔既,不適合生產(chǎn)環(huán)境恕曲。
偽分布式模式的配置,只需將hbase.cluster.distributed屬性值設(shè)為true渤涌。而Hbase的數(shù)據(jù)既可以設(shè)置存儲在本地佩谣,也可以保存到hdfs上。如下面的配置(這里Hbase數(shù)據(jù)存儲在本地):
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///home/hadoop/hbasedata/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/hadoop/hbasedata/zk</value>
</property>
</configuration>
在偽分布式模式下实蓬,通過bin目錄下的hbase-daemon.sh來分別啟動各個服務(wù)進程茸俭,操作如下:
hbase-daemon.sh start zookeeper
hbase-daemon.sh start master
hbase-daemon.sh start regionserver
通過上面的操作分別啟動zookeeper服務(wù)進程吊履,HBASE mater服務(wù)進程,HBASE regionserver服務(wù)進程瓣履。這時我們執(zhí)行jps命令,會看到3個相關(guān)的進程:
[hadoop@localhost ~]$ jps
17585 HRegionServer
17349 HMaster
17212 HQuorumPeer
如果要關(guān)閉各個服務(wù)练俐,可以依次執(zhí)行下面三個操作:
hbase-daemon.sh stop regionserver
hbase-daemon.sh stop master
hbase-daemon.sh stop zookeeper
在偽分布式下袖迎,我們也可以不用Hbase自帶的zookeeper,而是使用獨立安裝的zookeeper腺晾。關(guān)于獨立zookeeper的安裝燕锥,本文不再介紹,可參見《Zookeeper學(xué)習(xí)筆記》一文悯蝉。
(三)分布式模式
在實際生產(chǎn)環(huán)境下归形,會采用分布式模式來啟動Hbase。在分布式模式下鼻由,HBase守護進程的多個實例在集群中的多個服務(wù)器上運行暇榴。分布式的配置要求將hbase.cluster.distributed屬性設(shè)置為true。通常情況下蕉世,hbase.rootdir被配置為指向高可用性的HDFS文件系統(tǒng)蔼紧。這時集群系統(tǒng)將包含多個運行在不同服務(wù)器上的RegionServer,以及主要和備份Master和ZooKeeper守護程序(也是以集群方式部署)狠轻。
關(guān)于集群環(huán)境下的Hbase分布式部署奸例,本文不作詳細介紹。
六向楼、Hbase命令行
Hbase服務(wù)啟動后(最簡單的方式就是使用本地文件系統(tǒng)以獨立模式啟動Hbase)查吊,就可以利用Hbase客戶端程序訪問Hbase服務(wù)了。
Hbase安裝包中提供了一個命令行腳本hbase湖蜕,位于bin目錄下逻卖。在控制臺下運行 hbase shell ,會出現(xiàn)交互式命令行程序(時間可能有點長昭抒,實際是啟動了一個java進程)箭阶,可以執(zhí)行操作Hbase的各種命令,如:
[hadoop@localhost ~]$ hbase shell
...................................
Took 0.0042 seconds
hbase(main):001:0>
在提示符下輸入help命令可以查看幫助信息戈鲁。
1仇参、查看用戶空間下的所有表:
hbase(main):018:0> list
TABLE
0 row(s)
Took 0.0042 seconds
2、創(chuàng)建表:
hbase(main):063:0> create 'test','cf1','cf2'
Created table test
Took 0.7255 seconds
上面create命令創(chuàng)建了一個表婆殿,表名叫test诈乒,有2個列族cf1和cf2,屬性采用默認的婆芦。注意hbase命令后的參數(shù)要用引號括起來怕磨。
這時我們?nèi)绻賵?zhí)行l(wèi)ist命令喂饥,就能查到剛創(chuàng)建的test表。
3肠鲫、查看表的信息
hbase(main):064:0> desc 'test'
Table test is ENABLED
test
COLUMN FAMILIES DESCRIPTION
{NAME => 'cf1', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DAT
A_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW',
CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION =>
'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}
{NAME => 'cf2', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DAT
A_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW',
CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION =>
'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}
2 row(s)
Took 0.0245 seconds
4员帮、往表中插入數(shù)據(jù):
hbase(main):066:0> put 'test','row1','cf1:a', 'a123'
Took 0.0244 seconds
hbase(main):067:0> put 'test','row1','cf1:b', 'b123'
Took 0.0045 seconds
上面操作,插入了兩個數(shù)據(jù)导饲,插入的是一行數(shù)據(jù)捞高,行的關(guān)鍵字值為row1,列族cf1有兩個成員渣锦,標(biāo)示符分別是a和b硝岗。可以看出袋毙,put命令實際是往單元格中插入值型檀。hbase表的列只是在數(shù)據(jù)插入時才確定。
5听盖、查看表中所有數(shù)據(jù)
hbase(main):068:0> scan 'test'
ROW COLUMN+CELL
row1 column=cf1:a, timestamp=1544099621874, value=a123
row1 column=cf1:b, timestamp=1544099630279, value=b123
1 row(s)
Took 0.0099 seconds
6胀溺、查看表中指定行、列族皆看、列的數(shù)據(jù)
hbase(main):069:0> get 'test','row1'
COLUMN CELL
cf1:a timestamp=1544099621874, value=a123
cf1:b timestamp=1544099630279, value=b123
1 row(s)
Took 0.0162 seconds
hbase(main):070:0>
hbase(main):071:0* get 'test','row1','cf1'
COLUMN CELL
cf1:a timestamp=1544099621874, value=a123
cf1:b timestamp=1544099630279, value=b123
1 row(s)
Took 0.0118 seconds
hbase(main):072:0> get 'test','row1','cf1:b'
COLUMN CELL
cf1:b timestamp=1544099630279, value=b123
1 row(s)
Took 0.0063 seconds
7月幌、查看多版本數(shù)據(jù)
因為hbase表中的單元格可以允許存儲多版本數(shù)據(jù),但默認創(chuàng)建表的情況下悬蔽,各列族允許的存儲版本數(shù)的個數(shù)是1,可以通過desc命令能查看到扯躺。可以通過alter命令來重新修改蝎困,語法如:
alter '表名',{NAME=>'列族名',VERSIONS=>允許的版本數(shù)}
如下面例子:
hbase(main):073:0> alter 'test',{NAME=>'cf2',VERSIONS=>3}
Updating all regions with the new schema...
1/1 regions updated.
Done.
Took 1.8416 seconds
hbase(main):074:0> put 'test','row1','cf2:a','data1'
Took 0.0079 seconds
hbase(main):075:0> put 'test','row1','cf2:a','data2'
Took 0.0035 seconds
hbase(main):076:0> put 'test','row1','cf2:a','data3'
Took 0.0034 seconds
hbase(main):082:0> get 'test','row1','cf2:a'
COLUMN CELL
cf2:a timestamp=1544104507106, value=data3
1 row(s)
Took 0.0143 seconds
hbase(main):084:0> get 'test','row1',{COLUMN=>'cf2:a',VERSIONS=>3}
COLUMN CELL
cf2:a timestamp=1544104507106, value=data3
cf2:a timestamp=1544104503371, value=data2
cf2:a timestamp=1544104498175, value=data1
1 row(s)
Took 0.0091 seconds
可以看出录语,在get命令后加上 {COLUMN=>'cf2:a',VERSIONS=>3}參數(shù)可以返回多個版本的值。
8禾乘、刪除數(shù)據(jù)
刪除指定的行下的某個列族下的列(即某個單元格)
delete 'test','row1','data:a'
刪除整行
deleteall 'test','row1'
9澎埠、禁用表
hbase(main):012:0> disable 'test'
Took 0.8346 seconds
在hbase中,刪除表之前始藕,必須先禁用表后才能刪除蒲稳。
10、刪除表
hbase(main):012:0> drop 'test'
Took 0.4346 seconds
在實際應(yīng)用中伍派,我們一般會通過編寫程序的方式去使用Hbase江耀。最常見的是使用Hbase提供的java api來編寫Hbase客戶端程序。關(guān)于Hbase的java api的使用诉植,在后面文章進行介紹祥国。