博客 / 詳情

返回

【Hadoop】HBase系統解析及適用場景

一、HBase產生背景

在大數據時代,傳統的關係型數據庫(如Mysql、Oracle)在大數據量下的併發讀寫及可拓展性方面遇到瓶頸,尤其是處理海量的非結構化、半結構化數據時效率較低,而Hadoop的HDFS雖然支持海量數據的存儲以及批處理,但其無法支持隨機讀寫和低延遲查詢(HDFS 中的文件一旦寫入不能修改,只能追加),所以HBase被設計出來,彌補了HDFS在實時訪問能力上的不足。

HBase是一個基於列式存儲的分佈式數據庫(實質是一個KV數據庫),它的設計靈感來自於Google 2006 年發表的論文《Bigtable: A Distributed Storage System for Structured Data》(BigTable也是一種基於列式存儲、支持高吞吐、低延遲、可管理海量數據的分佈式數據庫)

HBase主要有以下幾點特性:

  1. 提供實時讀寫能力(採用LSM樹 + 內存緩存的方式實現毫秒級的隨機讀寫)
  2. 採用列式存儲,適合存儲半結構化、非結構化的數據(無法明確有哪些列的情況)
  3. 高拓展性和高可用性(通過Region分片機制和Zookeeper協調服務,可拓展至數百節點)
  4. 多版本控制(默認保留3個歷史版本)

二、HBase系統架構

HBase也是採用的主從架構,並且依賴Zookeeper實現動態擴展、故障轉移。系統架構圖如下:
image.png
主要有以下幾種組件:
HMaster:集羣的Master節點

  • 元數據管理:管理表的元數據(如表的 Schema、列族配置,存儲路徑為 /hbase/data/<命名空間>/<表名>/.tableinfo)和 Region 的分佈信息(存儲在hbase:meta系統表中,存儲路徑為 /hbase/data/hbase/meta/)
  • Region的分配:負責 Region 的分配 及 RegionServer 故障時的 Region 遷移
  • 處理DDL操作:處理表的增、刪、改操作
  • 維護系統表:管理hbase:meta系統表

HRegionServer:Region的管理節點

  • 管理Region:每個RegionServer會託管多個Region,處理這些Region的讀寫請求
  • Region分裂:當Region大小達到閾值,會對Region進行分裂
  • 依賴HDFS存儲:會將StoreFile和WAL日誌持久化到HDFS

Zookeeper:集羣的協調服務

  • 監控RegionServer:當RegionServer存活狀態異常,會通知HMaster進行Region遷移
  • 存儲hbase:meta系統表的位置:客户端通過zookeeper獲取Region的信息
  • HMaster的故障轉移:當主節點宕機,會選舉出一個新的leaer作為HMaster節點

HDFS:底層數據存儲

  • 數據持久化:存儲所有 Region 的 StoreFile(HFile 格式),並且還存儲WAL日誌
  • 高可用:多副本機制保障數據安全

這裏還有相關的一些概念:
Region:表部分數據的集合,表會根據RowKey值被切分成不同的 Region 被不同的RegionServer託管,這些Region組合起來就是一張表(每RegionServer會託管多個Region
Store:每個Store對應HBase表的一個列族的數據
MemStore:寫緩存,數據會先寫到MemStore中,並排好序,當MemStore達到閾值,則會刷寫到HDFS中,形成一個新的StoreFile
StoreFile:保存數據的實際物理文件,以HFile格式存儲在HDFS上(每個Store會有多個StoreFile,並且每個StoreFile內部有序

三、HBase數據模型

HBase的數據模型如下圖
image.png
Row:每行數據由一個RowKey和多個列組成,數據按照 RowKey字典順序存儲,所以在HBase中RowKey的設計是比較重要的
Column Family:列族,每個列族可以有多個列,並且可動態添加列,一個列族物理存儲時對應一個Store
Column:建表時無需聲明列,只需要聲明列族即可,列可以動態添加
TimeStamp:每條數據都有對應的時間戳,用於標識數據的不同版本(默認保留3個版本
Cell:通過{RowKey, 列族:列, TimeStamp} 唯一確定一個值

四、如何設計Rowkey?

由於HBase存儲數據時,是按照RowKey字典順序存儲,所以要充分利用RowKey排序的特點。

  1. 長度要求:RowKey本身可以是任意字符串,最大長度64k,但實際應用中一般小於100byte,因為RowKey本身也是佔用存儲空間的,假設一個RowKey 100個字節,一億條數據就有10G空間大小,所以RowKey不宜過長
  2. 大數據量的散列設計:由於HBase有多個RegionServer,所以要充分利用其並行處理的能力,假設RowKey按遞增的方式,那麼數據會產生熱點問題,大部分的數據會集中在某一兩個Region裏,這樣無法利用整個集羣的處理能力,所以數據量大的時候一般採用散列設計
  3. 頻繁訪問的就近設計:假設頻繁訪問某一部分數據,那麼這些數據的RowKey的前綴應儘量保持一致,這樣可以保證這些RowKey是存儲到同一個或相鄰的Region裏,有利於提高讀取效率

五、HBase的讀寫流程

5.1 讀取數據

image.png

客户端讀取數據時,大致流程如下:

  1. 客户端連接Zookeeper,獲取 hbase:meta 系統表的位置信息(存放在哪個RegionServer上)
  2. 客户端連接 hbase:meta 表所在的RegionServer,查詢 hbase:meta 系統表(meta表存儲了所有表的Region信息),客户端通過RowKey匹配到目標Region所在的RegionServer(可能匹配到多個Region)
  3. 客户端連接對應的RegionServer,攜帶RowKey發送讀取請求
  4. RegionServer根據RowKey定位到Region,Region內部按列族劃分為多個Store,每個Store包含一個MemStore和多個StoreFile(以HFile格式存儲),讀取時通過 多層索引 快速定位HFile磁盤文件中的目標數據塊,並且還會查詢MemStore中的數據
  5. 將多個HFile的查詢結果和MemStore的查詢數據進行合併,按時間戳排序,將最新的數據返回給客户端

5.2 寫入數據

image.png

  1. 客户端連接Zookeeper,獲取 hbase:meta 系統表,定位到目標Region所在的RegionServer(與讀取類似)
  2. 客户端連接對應的RegionServer,發起寫入請求
  3. RegionServer會先將寫入操作記錄到預寫日誌(WAL)中(WAL文件是存儲在HDFS上的),再將數據寫入到MemStore寫緩存(MemStore是有序的內存結構
  4. 寫入MemStore成功後立即向客户端返回寫入成功
  5. MemStore數據達到閾值時,觸發flush操作,將內存數據持久化成StoreFile(每次都會生成一個新的HFile,並按RowKey有序存儲)
  6. 隨着越來越多的HFile產生,HBase會定期合併這些這些HFile,包括Minor Compaction和Major Compaction(Minor Compaction會將相鄰的多個HFile合併成一個大的HFile,而Major Compaction會將一個列族的所有HFile全部合併為一個HFile)

六、Region的分裂

Region不可能無限擴大,所以當Region的大小超過閾值(默認10G)時,HBase會將其分裂為兩個子Region,以實現負載均衡。

觸發條件

  • 默認策略:當Region的大小超過閾值(默認10G)時觸發分裂
  • 其他策略:可以通過 hbase.regionserver.region.split.policy 進行配置
  • 手動觸發:通過shell或api主動執行split命令

分裂步驟

  1. HBase 自動選擇 Region 中間位置的 RowKey 作為分裂點
  2. 父 Region 被標記為 SPLITTING 狀態,暫停父 Region 的寫入,分裂為兩個子 Region,創建兩個子 Region 目錄
  3. HMaster 將兩個子 Region 分配到其他 RegionServer(或當前節點)
  4. 更新hbase:meta系統表,添加兩個子Region的元數據

七、總結

HBase作為Hadoop 生態的"熱數據"存儲,優勢是具備高拓展、高吞吐寫、低延遲隨機讀以及與Hadoop生態的無縫集成,但缺點也很明顯,強依賴Zookeeper和HDFS,運維複雜度較高,並且無法進行復雜查詢、分析,所以HBase更適用於高併發寫入(如日誌系統)、實時查詢(如用户畫像)、動態列等應用場景。

user avatar u_16213628 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.