1. 程式人生 > >大資料儲存利器 - Hbase 基礎圖解

大資料儲存利器 - Hbase 基礎圖解

由於疫情原因在家辦公,導致很長一段時間沒有更新內容,這次終於帶來一篇乾貨,是一篇關於 Hbase架構原理 的分享。

 

Hbase 作為實時儲存框架在大資料業務下承擔著舉足輕重的地位,可以說目前絕大多數大資料場景都離不開Hbase。

 

今天就先從 Hbase 基礎入手,來說說 Hbase 經常用到卻容易疏忽的基礎知識。

 

本文主要結構總結如下:

 

 

Hbase 主從架構

Hbase 安裝依靠 Hadoop 與 Zookeeper,網上有很多安裝教程,安裝比較簡單,這裡我們就著重看下 Habse 架構,如圖:

 

 

 

 

可以從圖中看出,Hbase 也是主從架構,其中 HMaster 為主,HRegionServer 為從。

 

Zookeeper 主要儲存了Hbase中的元資料資訊,如哪個表儲存在哪個 HRegionServer 上;

 

HLog 是作為 Hbase 寫資料前的日誌記錄;

 

BLockCache 作為讀寫資料的快取;

 

HMaster:

 

  • 負責新Region分配到指定HRegionServer

     

  • 管理HRegionServer 間負載均衡,遷移 region

     

  • 當HRegionServer 宕機,負責 region 遷移

 

 

HRegionserver:

 

  • 響應客戶端讀寫請求

     

  • 管理Region

     

  • 切分變大的 Region

 

 

Region:

 

  • 一個 Region 對應一個 Table 表

     

  • Hbase 儲存的最小單元

 

 


 

 

 HBase 表結構

Hbase 列式儲存的結構與行式儲存不同,它的表模型類似下圖:

 

 

表中大致可以分為 rowKey 、列族 、版本號三大元素,列族下可以建立多個列,表中的每一個單元格又稱為 cell,需要注意的是 cell 並不是只有一個數據,它可以有多個版本從而實現在同一rowkey ,同一列族, 同一列下儲存多個數據。

 


 

 

重點來了,有了上面的鋪墊,接下來就可以進入正題部分了 ,下面我們來看下 Hbase 的架構原理。 

 

 

Hbase 架構原理

 

1. Hbase 的儲存原理

    

還回到上邊的架構圖,可以看到 一個 HRegionServer 上有多個 HRegion,一個 Region 實際上就對應了一張表,由於 region 的拆分機制,同一張表的資料可能不會在一個HRegionServer上, 但是一個 Region 肯定只存一張表的資料。

 

下面我們再看看 HRegion 裡面的結構:

 

 

 

從圖中我看可以看到以下幾點:

 

  •  一個region包含多個 store,其中 :

 

    • 一個列族就劃分成一個 store

       

    • 如果一個表中只有1個列族,那麼每一個region中只有一個store

       

    • 如果一個表中只有N個列族,那麼每一個region中有N個store

 

 

 

  • 一個store裡面只有一個memstore

     

    • memstore 是一塊記憶體,資料會先寫進 memstore,然後再把資料刷到硬碟

 

 

  • 一個store裡面有很多的StoreFile,最後資料以很多 HFile 這種資料結構存在HDFS上

     

    • StoreFile 是 Hfile 的抽象物件,說到StoreFile就等於HFile

       

    • 每次 memsotre 重新整理資料到磁碟,就生成對應的一個新的 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上讀取

    • 一部分作為Memstore,主要用來寫;

    • 另外一部分作為BlockCache,主要用於讀資料;

    • HBase上Regionserver的記憶體分為兩個部分

  • 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各一份

    • write ahead log :也稱為WAL,類似mysql中的binlog,用來做災難恢復時用,HLog記錄資料的所有變更,一旦資料修改,就可以從log中進行恢復。

  • 5、memstore達到閾值後把資料刷到磁碟,生成storeFile檔案

  • 6、刪除HLog中的歷史資料

     

4. Hbase 的 flush 與 compact 機制

 

概括來說,flush 是資料由 memstore 刷寫到磁碟的過程,compact 是 磁碟檔案合併的過程,如圖所示:

 

 

flush 機制

 

flush 大致可以分為三個階段,prepare 階段,flush 階段,commit 階段:

 

  • prepare 階段

     

 

遍歷當前 Region 中所有的 Memstore,將Memstore中當前資料集CellSkipListSet 做一個快照snapshot,之後建立一個新的CellSkipListSet,後期寫入的資料都會寫入新的CellSkipListSet中

 

  • flush 階段

     

 

遍歷所有Memstore,將 prepare階段生成的 snapshot 持久化為臨時檔案,臨時檔案會統一放到目錄.tmp下。這個過程因為涉及到磁碟IO操作,因此相對比較耗時

 

  • commit 階段

 

遍歷所有 Memstore,將 flush階段生成的臨時檔案移到指定的ColumnFamily目錄下,針對HFile生成對應的storefile和Reader,把storefile新增到HStore的storefiles列表中,最後再清空prepare階段生成的snapshot 。

 

flush 的觸發條件一般分為 memstore 級別,region 級別,regionServer 級別,HLog數量上限,具體配置可在官網文件中查詢到。

 

compact 機制 

 

從圖中可以看出 compact 合併機制,主要分為 小合併 、大合併兩個階段。

 

  • minor compaction 小合併

 

將Store中多個HFile合併為一個HFile,一次Minor Compaction的結果是HFile數量減少並且合併出一個更大的StoreFile,這種合併的觸發頻率很高。

 

 

  • major compaction 大合併

 

合併 Store 中所有的 HFile 為一個HFile,被刪除的資料、TTL過期資料、版本號超過設定版本號的資料。合併頻率比較低,預設7天執行一次,並且效能消耗非常大,建議生產關閉(設定為0),在應用空閒時間手動觸發。一般可以是手動控制進行合併,防止出現在業務高峰期。

 

5. Hbase 的 region 拆分 與 合併

 

region 的拆分

 

Q:

為什麼要拆分 region 呢?


A:

region中儲存的是大量的 rowkey 資料 ,當 region 中的資料條數過多, region 變得很大的時候,直接影響查詢效率.因此當 region 過大的時候.hbase會拆分region , 這也是Hbase的一個優點 。



  • region 拆分策略

 

0.94版本前預設切分策略,當region大小大於某個閾值(hbase.hregion.max.filesize=10G)之後就會觸發切分,一個region等分為2個region。

 

0.94版本~2.0版本預設切分策略 :根據拆分次數來判斷觸發拆分的條件

 

region split的計算公式是:

regioncount^3 * 128M * 2,當region達到該 size 的時候進行split

例如:

第一次split:1^3 * 256 = 256MB

第二次split:2^3 * 256 = 2048MB

第三次split:3^3 * 256 = 6912MB

第四次split:4^3 * 256 = 16384MB > 10GB,因此取較小的值10GB

後面每次split的size都是10GB了

 

  • 預分割槽機制

 

當一個Hbase 表剛被建立的時候,Hbase預設的分配一個 region 給table。也就是說這個時候,所有的讀寫請求都會訪問到同一個 regionServer 的同一個region中,這個時候就達不到負載均衡的效果了,叢集中的其他 regionServer 就可能會處於比較空閒的狀態。

 

為了解決這個問題,就有了 pre-splitting,也就是預分割槽機制,在建立table的時候就配置好,生成多個region,這樣的好處就是可以優化資料讀寫效率;並且使用負載均衡機制,防止資料傾斜。

 

操作很簡單,在建立表時,手動指定分割槽就好了:

 

create 'person','info1','info2',SPLITS => ['1000','2000','3000','4000']

 

 

region 的合併

 

Region的合併不是為了效能,  而是出於維護的目的 。

 

比如刪除了大量的資料 ,這個時候每個Region都變得很小 ,儲存多個 Region就浪費了 ,這個時候可以把Region合併起來,進而可以減少一些 Region 伺服器節點,由此可見 region 的合併其實是為了更好的維護 Hbase 叢集。

 

至此,正文內容就結束了,為了更好的梳理這些知識,我將文章中重要的部分都放到下面這張圖中,方便以後總結查閱:

 

 

PS:後續文章更新方向除涉及大資料框架方向外,額外新增 C 語言和資料結構等計算機基礎方向,敬請期待 ~