HBase是一個分佈式的、面向列的開源數據庫存儲系統,是對Google論文BigTable的實現,具備高可靠性、高性能和可伸縮性,它能夠處理分佈在數千臺通用服務器上的PB級的海量數據。BigTable的底層是經過GFS(Google文件系統)來存儲數據,而HBase對應的則是經過HDFS(Hadoop分佈式文件系統)來存儲數據的。java
HBase不一樣於通常的關係型數據庫,它是一個適合於非結構化數據存儲的數據庫。HBase不限制存儲的數據的種類,容許動態的、靈活的數據模型。HBase能夠在一個服務器集羣上運行,而且可以根據業務進行橫向擴展。node
Column Family:Column Qualifier
表示。列是能夠隨意定義的,一個行中的列不限名字,不限數量,只限定列族。物理視圖算法
在物理存儲上,數據是以Key-Vaule對形式存儲,每一個Key-Value只存儲一個Cell裏面的數據,不一樣的列族存儲在不一樣的文件中,每一個邏輯單元格(Cell)會對應一行數據,有Timestamp標記版本,每次插入、刪除都會生成一行數據(append-only,寫效率高)。shell
HBase的服務器體系結構遵循簡單的主從服務器架構,通常一個HBase集羣由一個Master服務(高可用的話,至少兩個)和1個或多個RegionServer服務組成。Master服務負責維護表結構信息,實際的數據是保存在RegionServer上,最終RegionServer保存的表數據會直接存儲在HDFS上。HBase的體系架構圖以下圖所示:數據庫
Master HBase的管理節點,在一個集羣中Master通常是主備的,主備的選擇是由Zookeeper實現的。api
HBase Master主要職責:數組
RegionServer緩存
RegionServer主要負責服務和管理Region。在分佈式集羣中,建議RegionServer和DataNode按照1:1
比例部署,這樣RegionServer中的數據文件能夠存儲一個副本於本機的DataNode節點中,從而在讀取數據時能夠利用HDFS的"短路徑讀取(Short Circuit)"來繞過網絡請求,下降讀延時。性能優化
RegionServer內部管理一個或多個Region。Region許多Store組成。每一個Store對用Table中的一個列族存儲,即一個Store管理一個Region上的一個列族。每一個Store包含一個MemStore和0到多個StoreFile。服務器
RegionServer的主要職責:
Zookeeper
HBase經過Zookeeper來作Master的高可用、RegionServer的監控、元數據的入口以及集羣配置的維護等工做。具體工做以下:
hbase:meta
表信息;HDFS
HDFS爲HBase提供最終的底層數據存儲服務,同時爲HBase提供高可用(HLog)的支持。HBase底層存儲並不是必須是HDFS文件系統,可是HDFS是最佳選擇,也是目前應用最普遍的選擇。HDFS具體功能以下:
Client
Client使用HBase的RPC機制與HMaster、RegionServer進行通訊,Client與Master進行管理類通訊,與RegionServer進行數據操做類通訊。Client包含了訪問HBase的接口,另外Client還維護了對應的cache來加速HBase的訪問,好比.META.
元數據信息。
用戶寫入的數據先寫入WAL,而後寫入MemStore,當MemStore滿了之後會Flush成一個StoreFile(存儲爲HFile),當StoreFile數量到達必定閾值,會觸發Compact合併,將多個StoreFile合併成一個StoreFile。StoreFiles合併後會逐漸造成愈來愈大的StoreFile,當Region內的全部的StoreFiles的總的大小超過閾值(hbase.hregion.max.filesize
)會觸發Split操做。會把當前Region Split成兩個Region,父Region下線,新Split的兩個子Region被Master分配到合適的RegionServer上,使得原先一個Region的壓力分流到兩個Region上。
在進行數據操做的時候,首先要定位須要對哪一個Region進行操做,或者從哪一個Region上讀取數據,所以HBase數據讀取的第一步是Region尋址。
Region尋址步驟:
hbase:meta
表所在的RegionServer的地址(/hbase/meta-region-server
)。hbase:meta
表所在的RegionServer,獲取須要訪問的數據所在的RegionServer地址。Client會將hbase:meta
表的相關信息緩存起來,以便下一次可以快速訪問。hbase:meta
表存儲了全部Region的行鍵範圍信息,經過這個表能夠查詢出你要操做的Rowkey屬於哪一個Region的範圍裏面,以及這個Region是屬於哪一個RegionServer。細節:
HBase使用MemStore和StoreFile存儲對象表的更新,數據在更新的時候首先寫入HLog和MemStore。MemStore中的數據時排序的,當MemStore累積到必定閾值時,就會建立一個新的MemStore並將老的MemStore添加到flush隊列,由單獨的線程flush到磁盤上,成爲一個StoreFile。同時,系統會在Zookeeper中記錄一個checkpoint,表示這個時刻以前的更新已經持久化了,當系統出現意外時,可能致使MemStore中的數據丟失,此時使用HLog來恢復chckpoint以後的數據。
BlockCache
中查找數據,找不到再去MemStore
和StoreFile
中查詢數據 在對HBase進行寫操做的時候,進行Put和Update操做的時候,實際上是新增了一條數據,即便是在進行Delete操做的時候,也是新增一條數據,只是這條數據沒有value,類型爲DELETE,這條數據叫作墓碑標記(Tobstone)。數據的真正刪除是在compact操做時進行的。
WAL(Write-Ahead Log,預寫日誌)主要用來來解決宕機以後的操做恢復問題的。數據到達Region的時候會先寫入WAL,而後再被寫入MemStore。就算Region的機器宕掉了,因爲WAL的數據時存儲在HDFS中的,因此數據並不會丟失,還能夠從WAL中恢復。
產生
全部涉及到數據的變動都會先寫到HLog中,除非是關閉了HLog。
滾動
HLog的大小能夠經過參數hbase.regionserver.logroll.period
來控制,默認是1小時,時間達到該參數設置的時間,HBase會建立一個新的HLog文件。這就實現了HLog滾動的目的。HBase經過hbase.regionserver.maxlogs
參數控制HLog的個數。滾動的目的是爲了不單個HLog文件過大的狀況,方便後續的過時和刪除。
過時
HLog的過時依賴於sequenceid的判斷。HBase會將HLog的sequenceid和HFile最大的sequenceid(刷新到的最新位置)進行比較,若是該HLog文件中的sequenceid比刷新的最新位置的sequenceid都要小,那麼這個HLog就過時了,對應HLog會被移動到/hbase/oldWALs
目錄。
由於HBase有主從同步的功能,這個是依賴於HLog來同步HBase的變動,因此HLog雖然過時,也不會當即刪除,而是移動到別的目錄中。再增長對應的檢查和保留時間機制。
刪除
若是HBase開啓了replication,當replication執行完一個HLog的時候,會刪除Zookeeper上的對應HLog節點,在HLog被移動到/hbase/oldWALs
目錄後,HBase每隔hbase.master.cleaner.interval
(默認60秒)時間會去檢查/hbase/oldWALs
目錄下的全部HLog,確認對應的Zookeeper的HLog節點是否被刪除,若是Zookeeper上不存在對應的HLog節點,那麼久直接刪除對應的HLog。
hbase.master.logcleaner.ttl
(默認10分鐘)這個參數用來控制HLog在/hbase/oldWALs
目錄保留的最長時間。
爲了提升HBase的寫入性能,當寫請求寫入MemStore後,不會當即刷盤,而是會等到必定的時候再進行刷盤操做。
發生MemStore刷盤場景:
1. 全局內存控制
當整個RegionServer中全部MemStore佔用的內存達到閾值的時候,會觸發刷盤的操做。
2. MemStore達到上限
當MemStore佔用內存的大小達到hbase.hregion.memstore.flush.size
的值的時候會觸發刷盤,默認128M。
3. RegionServer的HLog數量達到上限
若是HLog太多的話,會致使故障恢復的時間過長,所以HBase會對HLog的最大個數作限制。當達到HLog的最大個數的時候,會強制刷盤(hbase.regionserver.max.logs
,默認32個)。
4. MemStore達到刷寫時間間隔
當MemStore達到時間間隔的閾值,會觸發刷寫操做,hbase.regionserver.optionalcacheflushinterval
,默認3600000,即1小時,若是設置爲0,則意味着關閉定時自動刷寫。
5. 手工觸發
能夠經過hbase shell或者java api手工觸發flush的操做
6. 關閉RegionServer觸發
當正常關閉RegionServer會觸發刷盤的操做,所有數據刷盤後就不須要再使用HLog恢復數據
7. Region使用HLog恢復完數據後觸發
當RegionServer出現故障的時候,其上面的Region會遷移到其餘正常的RegionServer上,在恢復完Region的數據後,會觸發刷盤,當刷盤完成後纔會提供給業務訪問。
隨着業務的發展,在表中的數據會愈來愈多,Region會愈來愈大,這樣會嚴重影響數據讀取效率。因此當一個Region變的過大後,會觸發Split操做,將一個Region分裂成兩個子Region。Region的拆分分爲自動拆分和手動拆分兩種。
Region拆分流程
/hbase/region-in-transition/region-name
下中建立一個znode。.splits
」的子目錄。NotServingRegionException
,client將重試。.splits
目錄下的region目錄,並建立必要的數據結構。而後拆分存儲文件,即先在父region中建立每一個存儲文件兩個reference文件。這兩個reference文件將指向父region文件。.META.
表,並在.META.
表中將父region設置爲offline,表並添加有關子region的信息。此時,.META.表中不會有每一個子region的單獨的條目。client能夠經過scan .META.
表來知曉父region正在拆分,可是除非子region信息記錄到.META.
表,不然client是看不到子region的。若是前面的Put操做成功寫入到.META.
表,則標誌父region拆分完成。若是RegionServer在put操做前返回失敗,則Master和打開這個region的RegionServer將會清除region拆分的錯誤狀態,若是.META.表成功更新,則region拆分狀態會被Master向前翻。.META.
表。以後,client就能夠發現新的region,並訪問之。client本地緩存.META.
表信息,可是當它們訪問RegionServer或者.META.
表時,本地緩存失效,client從.META.
表獲取新的region信息。/hbase/region-in-transition/region-name
節點中的region狀態到SPLIT,以便master感知其狀態變化。若是須要的話,負載器能夠將子region自由地指定到其它region。爲了減小對業務的影響,Region Split過程並不會真正將父Region中的HFile數據搬到子Region目錄中。Split過程僅僅是在子Region中建立了到父Region的HFile的引用文件,子Region1中的引用文件指向原HFile的上部,而子Region2的引用文件指向原HFile2的下部。數據的真正搬遷工做是在Compaction過程當中完成的。
Region的合併分爲小合併(Minor Compaction)和大合併(Major Compaction)。
當MemStore達到hbase.hregion.memstore.flush.size
大小的時候會將數據刷寫到磁盤,生成StoreFile。隨着業務的發展,數據量會愈來愈大,會產生不少的小文件,對於HBase的數據讀取,若是要掃描大量的小文件,會致使性能不好,所以須要將這些小文件合併成一個大一點的文件。
所謂的小合併,就是把多個小的StoreFile組合在一塊兒,造成一個較大的StoreFile,一般是累積到3個SotreFile後執行。經過hbase.hstore.compationThreadhold
參數配置,小合併的步驟以下:
/hbase/.tmp
目錄下的臨時文件中;這種小合併通常速度比較快,對業務的影響也比較小。本質上,小合併就是使用短期的IO消耗以及帶寬消耗換取後續查詢的低延遲。在Minor Compaction過程當中,達到TTL(記錄保留時間)的數據會被移除,可是由墓碑標記的記錄不會被移除,由於墓碑標記可能存儲在不一樣HFile中,合併可能會跨過部分墓碑標記。
大合併就是將一個Region下的全部StoreFile合併成一個大的StoreFile文件。在大合併的過程當中,以前刪除的行和過時的版本都會被刪除。大合併通常一週作一次,由hbase.hregion.majorcompaction
參數控制。大合併的影響通常比較大,儘可能避免同一時間多個Region進行合併,所以HBase經過hbase.hregion.majorcompaction.jitter
參數來進行控制,用於防止多個Region同時進行大合併。
具體算法:
hbase.hregion.majorcompaction
參數的值乘以一個隨機分數,這個隨機分數不能超過hbase.hregion.majorcompation.jitter
的值(默認爲0.5)。
經過hbase.hregion.majorcompaction
參數的值加上或減去hbase.hregion.majorcompaction
參數的值乘以一個隨機分數的值就肯定下一次大合併的時間區間。
能夠經過hbase.hregion.majorcompaction
設置爲0來禁用major compaction。
在Zookeeper中保存着RegionServer的相關信息,在RegionServer啓動的時候,會在Zookeeper中建立對應的臨時節點。RegionServer經過Socket和Zookeeper創建session會話,RegionServer會週期性的向Zookeeper發送ping消息包,以此說明本身還處於存活狀態。而Zookeeper收到ping包後,則會更新對應Session的超時時間。
當Zookeeper超過session超時時間還未收到RegionServer的ping包,則Zookeeper會認爲該RegionServer出現故障,Zookeeper會將該RegionServer對應的臨時節點刪除出,並通知Master,Master收到RegionServer掛掉的信息後就會啓動數據恢復流程。
PS:固然學習以上這麼多,只能說是剛剛入門,要想繼續深刻學習。別擔憂,在這裏爲你們準備了學習資料(暫時不透露,嘿嘿),長按識別如下二維碼,關注"DigNew"公衆號,並在後臺回覆"HBase"便可以獲取資料哈~(建議複製,避免錯字)
好文推薦: