本文主要圍繞以下三方面來討論HBase:是什么、為什么、怎樣做。
1. 什么是HBase
HBase是一個開源的、分布式的、非關系型數據庫,其設計思想來源於Google的Big Table。通過集群管理大表(十億行百萬列),提供隨機、實時的讀寫能力。

兩個問題需要解釋:
1.1 什么是非關系型數據庫?

1.2 HBase與HDFS的關系
HDFS為HBase提供物理存儲,可簡單將HDFS理解成提供海量存儲能力的文件系統(管理集群中的硬盤資源, 提供存儲空間和數據間的交互能力),HBase是將數據結構化存儲的方法(提供數據與結構化數據間的封裝能力),具體的數據需要落地在HDFS上。
2. 為什么選用HBase
2.1 海量存儲
Hbase適合存儲PB級別的海量數據,在PB級別的數據以及采用廉價PC集群存儲的情況下,能在幾十到百毫秒內返回數據。
2.2 列式存儲
這里的列式存儲其實說的是列族(ColumnFamily)存儲,Hbase是根據列族來存儲數據的。列族下面可以有非常多的列,列族在創建表的時候就必須指定。
下圖為HBase的表格結構,"address","info"為列族,在列族中,你可以指定任意多的列,在列數據為空的情況下,是不會占用存儲空間的,如RowKey為"xiaomming"的"town"為空。

2.3 極易擴展
Hbase的擴展性主要體現在兩個方面,一個是基於RegionServer對邏輯存儲結構Region的擴展,一個是基於HDFS對物理存儲空間的擴展。通過橫向添加RegionSever的機器,進行水平擴展,提升Hbase上層的處理能力,提升Hbsae服務更多Region的能力。
2.4 高並發
由於Hbase運行在廉價的PC集群上,因此單個IO的延遲其實並不小,一般在幾十到上百ms之間。這里說的高並發,主要是在並發的情況下,Hbase的單個IO延遲下降並不多。能獲得高並發、低延遲的服務。
2.5 高可用
HBase依賴Zookeeper實現HMaster的高可用:Zookeeper提供Leader Election機制並存儲狀態信息,在集群中啟動多個Master進程,讓它們連接到Zookeeper。其中一個Master進程會被選舉為leader處於Active狀態,其他的Master會被指定為Standby模式。如果當前的leader Master進程掛掉了,會從Standby Master中選舉新leader,恢復舊Master的狀態提供服務。
RegionServer自動故障轉移:一旦RegionServer發生宕機,HBase都會馬上檢測到這種宕機,並且在檢測到宕機之后會將宕機RegionServer上的所有Region重新分配到集群中其他正常RegionServer上去,再根據HLog進行丟失數據恢復,恢復完成之后就可以對外提供服務,整個過程都是自動完成的,並不需要人工介入。

3. 怎樣使用HBase
如上圖所示,HBase的運行時有三個集群:
-
Zookeeper集群,負責HBase和HDFS集群的協調服務和配置服務。
-
HDFS集群,是一個分布式文件系統,有單一的名字空間。其中的節點有NameNode和DataNode,前者負責存儲文件系統的元數據(包括目錄名,文件名,等),后則負責存儲實際文件的塊。
-
HBase集群,其中的節點有Master和RegionServer。
3.1 HBase搭建
搭建集群模式需依賴Zookeeper和HDFS,需要配置運行環境以及Zookeeper與HDFS的節點ip,具體如下 :
| 參數文件 |
配置參數 |
參考值 |
| .bash_profile |
HBASE_HOME |
/root/training/hbase-1.3.1 |
| hbase-env.sh |
JAVA_HOME |
/root/training/jdk1.8.0_144 |
| HBASE_MANAGES_ZK |
true |
|
| hbase-site.xml |
hbase.rootdir |
hdfs://ip:port/hbase |
| hbase.cluster.distributed |
true |
|
| hbase.zookeeper.quorum |
ip |
|
| dfs.replication |
2 |
|
| hbase.master.maxclockskew |
180000 |
|
| regionservers |
ip1 ip2 |
3.2 HBase集群中數據的存儲
3.2.1 RegionServer存儲的數據
RegionServer創建Region對象用於存儲數據,同時創建一個HLog實例記錄更新數據的操作信息,一個RegionServer包含多個Region和一個HLog。
-
Region是HBase中分布式存儲和負載均衡的最小單元,但並不是存儲的最小單元。
-
Region由一個或者多個Store組成,每個store保存一個columns family,每個Strore又由一個memStore和0至多個StoreFile 組成。memStore存儲在內存中, StoreFile存儲在HDFS上。
Region寫數據之前會先檢查MemStore:
1. 如果此Region的MemStore已經有緩存已有寫入的數據, 則直接返回;
2. 如果沒有緩存, 寫入HLog(WAL:預寫日志),再寫入MemStore,成功后再返回。
3. 當所有之前寫入MemStore的數據已經持久化在HDFS,HLog會失效,HLog存在於HDFS之上的文件會刪除, HLog的生命周期結束。

3.2.2 Zookeeper存儲額數據
Zookeeper保存了HBase集群的信息:
-
/hbase/root-region-server ,Root region的位置
-
/hbase/table/-ROOT-,根元數據信息
-
/hbase/table/.META.,元數據信息
-
/hbase/master,當選的Mater
-
/hbase/backup-masters,備選的Master
-
/hbase/rs ,RegionServer的信息
-
/hbase/unassigned,未分配的Region
3.3 HBase的訪問接口
a. Java編程接口;
b. Hbase的命令行工具,操作指令如下:

3.4 HBase Rowkey的設計
由於HBase是通過Rowkey查詢的,一般Rowkey會存比較關鍵的檢索信息。設計Rowkey時,需要根據應用場景合理設計,使數據均勻分布在多個節點提高並發訪問效率。HBase中的數據是按照Rowkey的ASCII字典順序進行全局排序的。Rowkey的設計原則如下:
-
頻繁寫的場景,隨機Rowkey會獲得更好性能;
-
頻繁讀的場景,有序Rowkey效率更高;
-
對於時間連續的數據,有序的Rowkey更有利於進行分段查詢。
3.5 Region熱點問題
HBase默認建表時有一個Region,這個Region的rowkey是沒有邊界的,即沒有startkey和endkey,在數據寫入時,所有數據都會寫入這個默認的Region,隨着數據量的不斷增加,此Region已經不能承受不斷增長的數據量,會進行拆分(split),分成2個Region。在此過程中,會產生兩個問題:
1. 數據往一個Region上寫,會有寫熱點問題。Region熱點問題是指大量的client直接訪問集中在個別RegionServer上,導致單個RegionServer機器自身負載過高,引起性能下降甚至Region不可用。
2. Region split會消耗寶貴的集群I/O資源。
基於此在建表的時候,創建多個空region,並確定每個Region的起始和終止Rowkey,這樣只要Rowkey的設計能均勻的命中各個Region,就不會存在熱點問題,自然split的幾率也會大大降低。當然隨着數據量的不斷增長,Region最終還是會拆分。像這樣預先創建HBase表分區的方式,稱之為預分區,HBase支持命令行及JavaAPI定義預分區策略。
3.6 Region的拆分
如上所述,當Region大小超過設定值時會導致Region的拆分,使HBase擁有良好擴張性。HBase不同版本的默認拆分策略不同,2.0版本默認切分策略依然和待分裂Region所屬表在當前RegionServer上的Region個數有關系,如果Region個數等於1,切分閾值為flush size(128M) * 2,否則為MaxRegionFileSize(默認為10G),個人以為此拆分策略應結合預分區策略使用,針對大表和小表定義合理的分區數。
最后提下Phoenix,解決HBase不支持SQL的特點。它作為HBase內嵌的JDBC驅動,Phoenix查詢引擎會將SQL查詢轉換為一個或多個HBase掃描,並編排執行以生成標准的JDBC結果集。
