1、HBase的數據存儲原理
- 一個HRegionServer會負責管理很多個region
- 一個*region包含很多個store
- 一個列族就劃分成一個store**
- 如果一個表中只有1個列族,那麼每一個region中只有一個store
- 如果一個表中有N個列族,那麼每一個region中有N個store
- 一個store裏面只有一個memstore
- memstore是一塊內存區域,寫入的數據會先寫入memstore進行緩衝,然後再把數據刷到磁盤
-
一個store裏面有很多個StoreFile, 最後數據是以很多個HFile這種數據結構的文件保存在HDFS上
- StoreFile是HFile的抽象對象,如果說到StoreFile就等於HFile
- 每次memstore刷寫數據到磁盤,就生成對應的一個新的HFile文件出來
2、HBase數據讀流程
說明:HBase集羣,只有一張meta表,此表只有一個region,該region數據保存在一個HRegionServer上
- 1、客戶端首先與zk進行連接;從zk找到meta表的region位置,即meta表的數據存儲在某一HRegionServer上;客戶端與此HRegionServer建立連接,然後讀取meta表中的數據;meta表中存儲了所有用戶表的region信息,我們可以通過
scan 'hbase:meta'
來查看meta表信息 - 2、根據要查詢的namespace、表名和rowkey信息。找到寫入數據對應的region信息
- 3、找到這個region對應的regionServer,然後發送請求
- 4、查找並定位到對應的region
- 5、先從memstore查找數據,如果沒有,再從BlockCache上讀取
- HBase上Regionserver的內存分爲兩個部分
- 一部分作爲Memstore,主要用來寫;
- 另外一部分作爲BlockCache,主要用於讀數據;
- 6、如果BlockCache中也沒有找到,再到StoreFile上進行讀取
- 從storeFile中讀取到數據之後,不是直接把結果數據返回給客戶端,而是把數據先寫入到BlockCache中,目的是爲了加快後續的查詢;然後在返回結果給客戶端。
3. HBase寫數據流程
-
1、客戶端首先從zk找到meta表的region位置,然後讀取meta表中的數據,meta表中存儲了用戶表的region信息
-
2、根據namespace、表名和rowkey信息。找到寫入數據對應的region信息
-
3、找到這個region對應的regionServer,然後發送請求
-
4、把數據分別寫到HLog(write ahead log)和memstore各一份
-
5、memstore達到閾值後把數據刷到磁盤,生成storeFile文件
- 6、刪除HLog中的歷史數據
補充:
HLog(write ahead log):
也稱爲WAL意爲Write ahead log,類似mysql中的binlog,用來做災難恢復時用,HLog記錄數據的所有變更,一旦數據修改,就可以從log中進行恢復。
4、HBase的flush機制
4.1、flush觸發條件
4.1.1、memstore級別限制
- 當Region中任意一個MemStore的大小達到了上限(hbase.hregion.memstore.flush.size,默認128MB),會觸發Memstore刷新。
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>134217728</value>
</property>
4.1.2 、region級別限制
- 當Region中所有Memstore的大小總和達到了上限(hbase.hregion.memstore.block.multiplier hbase.hregion.memstore.flush.size,默認 2 128M = 256M),會觸發memstore刷新。
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>134217728</value>
</property>
<property>
<name>hbase.hregion.memstore.block.multiplier</name>
<value>2</value>
</property>
4.1.3、Region Server級別限制
- 當一個Region Server中所有Memstore的大小總和超過低水位閾值hbase.regionserver.global.memstore.size.lower.limit*hbase.regionserver.global.memstore.size(前者默認值0.95),RegionServer開始強制flush;
- 先Flush Memstore最大的Region,再執行次大的,依次執行;
- 如寫入速度大於flush寫出的速度,導致總MemStore大小超過高水位閾值hbase.regionserver.global.memstore.size(默認爲JVM內存的40%),此時RegionServer會阻塞更新並強制執行flush,直到總MemStore大小低於低水位閾值
<property>
<name>hbase.regionserver.global.memstore.size.lower.limit</name>
<value>0.95</value>
</property>
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value>0.4</value>
</property>
4.1.4、HLog數量上限
- 當一個Region Server中HLog數量達到上限(可通過參數hbase.regionserver.maxlogs配置)時,系統會選取最早的一個 HLog對應的一個或多個Region進行flush
4.1.5、定期刷新Memstore
- 默認週期爲1小時,確保Memstore不會長時間沒有持久化。爲避免所有的MemStore在同一時間都進行flush導致的問題,定期的flush操作有20000左右的隨機延時。
4.1.6、手動flush
- 用戶可以通過shell命令
flush ‘tablename’
或者flush ‘region name’
分別對一個表或者一個Region進行flush。
4.2、flush的流程
-
爲了減少flush過程對讀寫的影響,將整個flush過程分爲三個階段:
-
prepare階段:遍歷當前Region中所有的Memstore,將Memstore中當前數據集CellSkipListSet做一個快照snapshot;然後再新建一個CellSkipListSet。後期寫入的數據都會寫入新的CellSkipListSet中。prepare階段需要加一把updateLock對寫請求阻塞,結束之後會釋放該鎖。因爲此階段沒有任何費時操作,因此持鎖時間很短。
- flush階段:遍歷所有Memstore,將prepare階段生成的snapshot持久化爲臨時文件,臨時文件會統一放到目錄.tmp下。這個過程因爲涉及到磁盤IO操作,因此相對比較耗時。
- commit階段:遍歷所有Memstore,將flush階段生成的臨時文件移到指定的ColumnFamily目錄下,針對HFile生成對應的storefile和Reader,把storefile添加到HStore的storefiles列表中,最後再清空prepare階段生成的snapshot。
-
5、Compact合併機制
-
hbase爲了==防止小文件過多==,以保證查詢效率,hbase需要在必要的時候將這些小的store file合併成相對較大的store file,這個過程就稱之爲compaction。
- 在hbase中主要存在兩種類型的compaction合併
- ==minor compaction 小合併==
- ==major compaction 大合併==
4.3.1 minor compaction 小合併
-
在將Store中多個HFile合併爲一個HFile
在這個過程中會選取一些小的、相鄰的StoreFile將他們合併成一個更大的StoreFile,對於超過了TTL的數據、更新的數據、刪除的數據僅僅只是做了標記。並沒有進行物理刪除,一次Minor Compaction的結果是更少並且更大的StoreFile。這種合併的觸發頻率很高。
- minor compaction觸發條件由以下幾個參數共同決定:
<!--表示至少需要三個滿足條件的store file時,minor compaction纔會啓動-->
<property>
<name>hbase.hstore.compactionThreshold</name>
<value>3</value>
</property>
<!--表示一次minor compaction中最多選取10個store file-->
<property>
<name>hbase.hstore.compaction.max</name>
<value>10</value>
</property>
<!--默認值爲128m,
表示文件大小小於該值的store file 一定會加入到minor compaction的store file中
-->
<property>
<name>hbase.hstore.compaction.min.size</name>
<value>134217728</value>
</property>
<!--默認值爲LONG.MAX_VALUE,
表示文件大小大於該值的store file 一定會被minor compaction排除-->
<property>
<name>hbase.hstore.compaction.max.size</name>
<value>9223372036854775807</value>
</property>
4.3.2 major compaction 大合併
-
合併Store中所有的HFile爲一個HFile
將所有的StoreFile合併成一個StoreFile,這個過程還會清理三類無意義數據:被刪除的數據、TTL過期數據、版本號超過設定版本號的數據。合併頻率比較低,默認7天執行一次,並且性能消耗非常大,建議生產關閉(設置爲0),在應用空閒時間手動觸發。一般可以是手動控制進行合併,防止出現在業務高峯期。
-
major compaction觸發時間條件
<!--默認值爲7天進行一次大合併,--> <property> <name>hbase.hregion.majorcompaction</name> <value>604800000</value> </property>
-
手動觸發
##使用major_compact命令 major_compact tableName
<property>
<name>hbase.hregion.majorcompaction</name>
<value>604800000</value>
</property> -
手動觸發
##使用major_compact命令 major_compact tableName