HBase簡介
對大數據領域有一定了解的小伙伴對HBase應該不會陌生,HBase是Apache基金會開源的一個分布式非關系型數據庫,屬于Hadoop的組件。它使用Java編寫,需運行于HDFS文件系統之上。HBase與Hadoop中的其他組件一樣,可以運行在廉價硬件上,并可提供數10億行 X 數百萬列的大數據存儲、管理能力,以及隨機訪問和實時讀/寫能力。HBase的設計模型參考了Google的Bigtable,可以說是Bigtable的開源實現版本。
HBase特性
- 數據容量大,單表可以有百億行、百萬列,數據矩陣橫向和縱向兩個維度所支持的數據量級都非常具有彈性
- 多版本,每一列存儲的數據可以有多個version
- 稀疏性,為空的列并不占用存儲空間,表可以設計的非常稀疏
- 讀寫強一致,非 “最終一致性” 的數據存儲,使得它非常適合高速的計算聚合
- 自動分片,通過Region分散在集群中,當行數增長的時候,Region也會自動的切分和再分配
- Hadoop/HDFS集成,和HDFS開箱即用,不用太麻煩的銜接。擴展性強,只需要增加DataNode就可以增加存儲空間
- 豐富的“簡潔,高效”API,提供了Thrift/REST API,Java API等方式對HBase進行訪問
- 塊緩存,布隆過濾器,可以高效的列查詢優化
- 操作管理,Hbase提供了內置的web界面來操作,還可以監控JMX指標
- 高可靠,保證了系統的容錯能力,WAL機制使得數據寫入時不會因為集群異常而導致寫入數據丟失。故HBase選擇了CAP中的CP
-
面向列的存儲和權限控制,并支持獨立檢索,可以動態的增加列
- 列式存儲:其數據在表中是按照某列存儲的,這樣在查詢只需要少數幾個字段的時候,能大大減少讀取的數據量
-
高性能,具備海量數據的隨機訪問和實時讀寫能力
- 寫方面:底層的 LSM 數據結構和 Rowkey 有序排列等架構上的獨特設計,使得HBase具有非常高的寫入性能。
- 讀方面:region 切分、主鍵索引和緩存機制使得HBase在海量數據下具備一定的隨機讀取性能,針對 Rowkey 的查詢能夠達到毫秒級別
綜上,HBase是一個高可靠、高性能、面向列、可伸縮的分布式數據庫,是谷歌Bigtable的開源實現。主要用來存儲非結構化和半結構化的松散數據。HBase的目標是處理非常龐大的表,可以通過水平擴展的方式,利用廉價計算機集群處理由超過10億行數據和數百萬列元素組成的數據表。更多內容詳見官方文檔。
HBase提供的訪問接口
類型 | 特點 | 場合 |
---|---|---|
Native Java API | 最常規和高效的訪問方式 | 適合Hadoop MapReduce作業并行批處理HBase表數據 |
HBase Shell | HBase的命令行工具,最簡單的接口 | 適合管理HBase時使用 |
Thrift Gateway | 利用Thrift序列化技術進行訪問,支持C++、PHP、Python等多種語言 | 適合其他異構系統在線訪問HBase表數據 |
REST Gateway | 解除了語言限制,任何語言都可以通過該方式訪問HBase | 支持REST風格的HTTP API訪問HBase |
Pig | 使用 Pig Latin 流式編程語言來處理HBase中的數據 | 適合做數據統計 |
Hive | 簡單 | 當需要以類似SQL語言方式來訪問HBase的時候 |
HBase 與 HDFS 的區別
- HDFS是面向批量的訪問模式,其類型為文件系統,存儲的是文件類型的數據
- HBase是面向隨機訪問和實時讀寫模式,其類型為數據庫服務,存儲的是非結構化和半結構化的松散數據
- HBase 使用 HDFS 作為底層的文件系統,HBase 的數據最終會寫到 HDFS 中。就像其他的數據庫一樣,真正的數據是存儲在操作系統里的文件系統中的
- 打個不恰當的比方:它們的區別就像是Linux文件系統與MongoDB的區別
HBase 與關系數據庫的區別
數據類型:
- 關系數據庫采用關系模型,具有豐富的數據類型和存儲方式,HBase則采用了更加簡單的數據模型,它把數據存儲為未經解釋的字符串。
數據操作:
- 關系數據庫中包含了豐富的操作,其中會涉及復雜的多表連接。HBase操作則不存在復雜的表與表之間的關系,只有簡單的插入、查詢、刪除、清空等,因為HBase在設計上就避免了復雜的表和表之間的關系。所以HBase也就不支持復雜的條件查詢,只能是通過行鍵查詢。
存儲模式:
- 關系數據庫是基于行模式存儲的。HBase是基于列存儲的,每個列簇都由幾個文件保存,不同列簇的文件是分離的。并且列簇中的列是可以動態增加的,而關系數據庫需要一開始就設計好。除此之外,HBase可以自動切分數據,關系型數據庫則需要我們人工切分數據。
數據索引:
- 關系數據庫通常可以針對不同列構建復雜的多個索引,以提高數據訪問性能。HBase只有一個索引——行鍵,通過巧妙的設計,HBase中的所有訪問方法,或者通過行鍵訪問,或者通過行鍵掃描,從而使得整個系統不會慢下來。
數據維護:
- 在關系數據庫中,更新操作會用最新的當前值去替換記錄中原來的舊值,舊值被覆蓋后就不會存在。而在HBase中執行更新操作時,并不會刪除數據舊的版本,而是生成一個新的版本,舊有的版本仍然保留。
可伸縮性:
- 關系數據庫很難實現橫向擴展,縱向擴展的空間也比較有限。相反,HBase和BigTable這些分布式數據庫就是為了實現靈活的水平擴展而開發的,能夠輕易地通過在集群中增加或者減少硬件數量來實現性能的伸縮。
HBase 常見應用場景
- 存儲業務數據:交通工具GPS信息,司機點位信息,訂單信息,物流信息,設備訪問信息,用戶行為信息等
- 存儲日志數據:架構監控數據(登錄日志,中間件訪問日志,推送日志,短信郵件發送記錄等),業務操作日志信息等
- 存儲業務附件:UDFS系統存儲圖像,視頻,文檔等附件信息,智慧城市系統的監控圖像、流量數據等
HBase 的版本選擇與定位
如何選擇合適的 HBase 版本
HBase屬于Hadoop生態體系,所以HBase的版本選擇實際就是Hadoop的版本選擇。而Hadoop就像Linux一樣,也有多個發行版,常用發行版有以下幾種:
- 原生的Apache Hadoop
- CDH:Cloudera Distributed Hadoop
- HDP:Hortonworks Data Platform
原生的Apache Hadoop在生產環境中不建議使用,因為Apache社區里的Hadoop生態系統的框架只是解決了單個框架的問題,如果想要將不同的框架,例如Hive、Hbase等框架綜合起來使用的話,總是會產生jar包的沖突問題,而且這些沖突問題通常都是無法解決的。所以在學習的時候可以使用Apache Hadoop,但是生產環境中就不太建議使用了。
CDH以及HDP都是基于Apache Hadoop社區版衍生出來的,這兩個發行版雖然都是商業版的,但不屬于收費版本,除非需要提供技術服務,才需要收取一定的服務費用,并且它們也都是開源的。在國內絕大多數公司都會選擇使用CDH版本,所以在這里也主要介紹CDH,選擇CDH的主要理由如下:
- CDH對Hadoop版本的劃分非常清晰,目前只有三個系列的版本(現在已經更新到CDH6.32了,基于hadoop3.x),分別是cdh4、cdh5和cdh6,分別對應第一代Hadoop(Hadoop 1.0)、第二代Hadoop(Hadoop 2.0)和第三代Hadoop(Hadoop 3.0),相比而言,Apache版本則混亂得多;
- CDH文檔清晰且豐富,很多采用Apache版本的用戶都會閱讀cdh提供的文檔,包括安裝文檔、升級文檔等。
而且CDH提供了一個CM組件,讓我們在安裝它的時候只需要在瀏覽器上的頁面中,點擊各種下一步就可以完成安裝,比起Apache Hadoop的安裝要方便很多,而且很多操作都可以在圖形界面上完成,例如集群的搭建以及節點切換等。CDH與Spark的合作是非常好的,所以在CDH中對Spark的支持比較好。最主要的是一般情況下使用同一版本的CDH,就不會發生jar沖突的情況。
CDH6的下載地址如下:
注:選擇版本的時候盡量保持一致,例如hive選擇了cdh5.7.0的話,那么其他框架也要選擇cdh5.7.0,不然有可能會發生jar包的沖突。
HBase 在 Hadoop 生態系統中的定位
HBase 系統架構與數據模型
系統架構
大致的架構體系
在HBase中,表被分割成多個更小的塊然后分散的存儲在不同的服務器上,這些小塊叫做Region,存放Region的地方叫做RegionServer。Master進程負責處理不同的RegionServer之間的Region的分發。HBase里的HRegionServer和HRegion類代表RegionServer和Region。HRegionServer除了包含一些HRegion之外,還處理兩種類型的文件用于數據存儲。
- HBase 依賴 Zookeeper 作為分布式的協調、治理工具,RegionServer、Master也會把自己的信息寫到ZooKeeper中
- HBase 還依賴 HDFS 作為底層的文件系統,HBase 的數據最終是存儲到 HDFS 服務中的
- HBase 存在兩個主要進程,分別是RegionServer和Master
- HBase 中的 RegionServer,可以類比為 HDFS 的 DataNode 即數據節點。客戶端通過RegionServer對數據進行讀寫操作,而RegionServer會負責與 HDFS 進行數據交互
- RegionServer會實時向Master報告自身狀態及region等信息。Master知道全局的RegionServer運行情況,可以控制RegionServer的故障轉移和region的切分。Master相當于是RegionServer集群的管理者,并且任何時刻只有一個Master在運行
細化的架構體系
Client
- 客戶端包含訪問HBase的接口,同時在緩存中維護著已經訪問過的Region位置信息,用來加快后續數據訪問過程
Zookeeper
-
Zookeeper作為協調工具可以幫助選舉出一個Master作為集群的總管,并保證在任何時刻總有唯一一個Master在運行,這就避免了Master的“單點故障”的問題
image.png
Master
- 主要負責表和Region的管理工作
- 管理客戶端對表的增加、刪除、修改、查詢等操作
- 實現不同RegionServer之間的負載均衡
- 在Region分裂或合并后,負責重新調整Region的分布
- 對發生故障失效的RegionServer上的Region進行遷移
RegionServer
- RegionServer是HBase中最核心的模塊,負責維護分配給自己的Region,并響應用戶的讀寫請求。
- 用戶讀寫數據過程:
- 用戶寫入數據時,被分配到相應Region服務器去執行
- 用戶數據首先被寫入到MEMStore和Hlog中
- 只有當操作寫入Hlog之后,commit()調用才會將其返回給客戶端
- 當用戶讀取數據時,Region服務器首先訪問MEMStore緩存,如果找不到,再去磁盤上面的StoreFile中尋找
- 緩存的刷新:
- 系統會周期性地把MemStore緩存里的內容刷寫到磁盤的StoreFile文件中,清空緩存,并在Hlog里面寫入一個標記
- 每次刷寫都生成一個新的StoreFile文件,因此,每個Store包含多個StoreFile文件
- 每個Region服務器都有一個自己的HLog 文件,每次啟動都檢查該文件,確認最近一次執行緩存刷新操作之后是否發生新的寫入操作;如果發現更新,則先寫入MemStore,再刷寫到StoreFile,最后刪除舊的Hlog文件,開始為用戶提供服務。
- StoreFile的合并:
- 每次刷寫都生成一個新的StoreFile,數量太多,影響查找速度、
- 調用Store.compact()把多個合并成一個
- 合并操作比較耗費資源,只有數量達到一個閾值才啟動合并
讀寫流程示意圖:
HLog
- 預寫日志文件,也叫做WAL(write-ahead log),WAL位于
/hbase/WALs/
目錄下 - 通常情況,每個RegionServer只有一個WAL實例。在2.0之前,WAL的實現叫做HLog
MasterProcWAL
:HMaster
記錄管理操作,比如解決沖突的服務器,表創建和其它DDL等操作到它的WAL文件中,這個WALs存儲在MasterProcWALs
目錄下,它不像RegionServer的WALs,HMaster
的WAL也支持彈性操作,就是如果Master服務器掛了,其它的Master接管的時候繼續操作這個文件。
WAL記錄所有的HBase數據改變,如果一個RegionServer在MemStore進行FLush的時候掛掉了,WAL可以保證數據的改變被應用到。如果寫WAL失敗了,那么修改數據的完整操作就是失敗的。
MultiWAL
:如果每個RegionServer只有一個WAL,由于HDFS必須是連續的,導致必須寫WAL連續的,然后出現性能問題。MultiWAL
可以讓RegionServer同時寫多個WAL并行的,通過HDFS底層的多管道,最終提升總的吞吐量,但是不會提升單個Region的吞吐量。
HFile
- 真實存儲數據的文件,HFile是Hbase在HDFS中存儲數據的格式,它包含多層的索引,這樣在Hbase檢索數據的時候就不用完全的加載整個文件。索引的大小(keys的大小,數據量的大小)影響block的大小,在大數據集的情況下,block的大小設置為每個RegionServer 1GB也是常見的。
HFile的生成方式:
- 1、起初,HFile中并沒有任何Block,數據還存在于MemStore中
- 2、Flush發生時,創建HFile Writer,第一個空的Data Block出現,初始化后的Data Block中為Header部分預留了空間,Header部分用來存放一個Data Block的元數據信息
- 3、而后,位于MemStore中的KeyValues被一個個append到位于內存中的第一個Data Block中
- 4、如果配置了Data Block Encoding,則會在Append KeyValue的時候進行同步編碼,編碼后的數據不再是單純的KeyValue模式。Data Block Encoding是HBase為了降低KeyValue結構性膨脹而提供的內部編碼機制
表結構及數據模型
HBase 是一個稀疏、多維度、排序的映射表,這張表的索引是行鍵、列簇、列限定符和時間戳。在 HBase 中每個值都是一個未經解釋的字符串,沒有數據類型。用戶在表中存儲數據,每一行都有一個可排序的行鍵和任意多的列。
表在水平方向由一個或多個列簇組成,一個列簇中可以包含任意多個列,同一個列簇里面的數據存儲在一起。列簇支持動態擴展,可以很輕松地添加一個列簇或列,無需預先定義列的數量以及類型,所有列均以字符串形式存儲,用戶需要自行進行數據類型轉換。
在 HBase 中執行更新操作時,并不會刪除數據舊的版本,而是生成一個新的版本,舊的版本仍然保留(這是和HDFS只允許追加不允許修改的特性相關的),所以 HBase 的數據是版本化的。
- 表:HBase采用表來組織數據,表由行和列組成,列劃分為若干列簇。
- 行:每個HBase表都由若干行組成,每一行由行鍵(row key)來標識。
- 行鍵:每一行都會存在一個行鍵,可以類比為關系型數據庫中的主鍵
- 列簇:一個HBase表被分組成許多“列簇”(Column Family)的集合,列簇中的列是有序的,它是基本的訪問控制單元。在設計表時,列簇盡量不超過5個,否則會影響性能。
- 列限定符:列簇里的數據通過限定符(列名)來定位。每個列簇中的列數是沒有限制的,列只有在插入數據后才存在
-
單元格:在HBase表中,通過行、列簇和列限定符確定一個“單元格”(cell),單元格中存儲的數據沒有數據類型,總被視為字節數組
byte[]
- 時間戳:每個單元格都保存著同一份數據的多個版本,這些版本采用時間戳進行索引。
這是官方文檔中給出的一個示例表:
說明:
- 該表中包含兩行:
com.cnn.www
和com.example.www
- 有三個列簇:
contents
、anchor
和people
- 第一行(
com.cnn.www
)擁有5個版本,第二行(com.example.www
)擁有1個版本 - 對于第一行(
com.cnn.www
):-
contents
列簇中包含一列:contents:html
- 該列的值為某個網站的html內容
-
anchor
列簇中包含兩列:anchor:cnnsi.com
和anchor:my.look.ca
-
cnnsi.com
列的值為CNN
-
my.look.ca
列的值為CNN.com
-
-
people
列簇中沒有任何列
-
- 對于第二行(
com.example.www
):-
contents
列簇中包含一列:contents:html
- 該列的值為一段html
-
anchor
列簇中沒有任何列 -
people
列簇中包含一列:people:author
- 該列的值為
John Doe
- 該列的值為
-
使用json格式表示該表內容如下:
{
"com.cnn.www": {
contents: {
t6: contents:html: "<html>..."
t5: contents:html: "<html>..."
t3: contents:html: "<html>..."
}
anchor: {
t9: anchor:cnnsi.com = "CNN"
t8: anchor:my.look.ca = "CNN.com"
}
people: {}
}
"com.example.www": {
contents: {
t5: contents:html: "<html>..."
}
anchor: {}
people: {
t5: people:author: "John Doe"
}
}
}