1. 程式人生 > >hbase 文件組織方式 和 多級索引機制

hbase 文件組織方式 和 多級索引機制

使用 dfs star 超過 文件 數據讀寫 -c BE 存在

轉自

https://blog.csdn.net/u010039929/article/details/74217793

並且參照了

https://blog.csdn.net/songjifei/article/details/54311927

說明:

hbase適合2中類型的查詢一種是實時數據的查詢,這些數據剛插入到hbase,很大可能還在MemStore中,所以查詢速度快。

另外一種是按照數據段的查詢,只要能把數據按照合理的順序排在一起,hbase中按照這個順序去查詢段內數據就會存儲的很近(很多是同一個文件),自然批量讀取就快。

說明2:

hbase的多級索引機制。

從上往下依次是 :

1、‘.META.‘表記錄用戶定義表region信息。其實就是每個hbase分區的起止的key和分區的位置。這樣首先就能確定要查找的key在哪個分區上(以及RegionServer)。

2、找到region後,這個裏面是多個文件,

HBase存儲架構

從HBase的架構圖上可以看出,HBase中的存儲包括HMaster、HRegionServer、HRegion、Store、MemStore、StoreFile、HFile、HLog等,本篇文章統一介紹他們的作用即存儲結構。

以下是HBase存儲架構圖:

技術分享圖片

HBase中的每張表都通過行鍵按照一定的範圍被分割成多個子表(HRegion),默認一個HRegion超過256M就要被分割成兩個,這個過程由HRegionServer管理,而HRegion的分配由HMaster管理。

HMaster的作用:

  • 為Region server分配region
  • 負責Region server的負載均衡
  • 發現失效的Region server並重新分配其上的region
  • HDFS上的垃圾文件回收
  • 處理schema更新請求

HRegionServer作用:

  • 維護master分配給他的region,處理對這些region的io請求
  • 負責切分正在運行過程中變的過大的region

可以看到,client訪問hbase上的數據並不需要master參與(尋址訪問zookeeper和region server,數據讀寫訪問region server),master僅僅維護table和region的元數據信息(table的元數據信息保存在zookeeper上),負載很低。

HRegionServer存取一個子表時,會創建一個HRegion對象,然後對表的每個列族創建一個Store實例,每個Store都會有一個MemStore和0個或多個StoreFile與之對應,每個StoreFile都會對應一個HFile, HFile就是實際的存儲文件。因此,一個HRegion有多少個列族就有多少個Store。

一個HRegionServer會有多個HRegion和一個HLog。

HRegion

table在行的方向上分隔為多個Region。Region是HBase中分布式存儲和負載均衡的最小單元,即不同的region可以分別在不同的Region Server上,但同一個Region是不會拆分到多個server上。

Region按大小分隔,每個表一行是只有一個region。隨著數據不斷插入表,region不斷增大,當region的某個列族達到一個閾值(默認256M)時就會分成兩個新的region。

每個region由以下信息標識:

  • <表名,startRowkey,創建時間>
  • 由目錄表(-ROOT-和.META.)可值該region的endRowkey

HRegion定位:

Region被分配給哪個Region Server是完全動態的,所以需要機制來定位Region具體在哪個region server。

HBase使用三層結構來定位region:

  • 1、 通過zk裏的文件/hbase/rs得到-ROOT-表的位置。-ROOT-表只有一個region。
  • 2、通過-ROOT-表查找.META.表的第一個表中相應的region的位置。其實-ROOT-表是.META.表的第一個region;.META.表中的每一個region在-ROOT-表中都是一行記錄。
  • 3、通過.META.表找到所要的用戶表region的位置。用戶表中的每個region在.META.表中都是一行記錄。

技術分享圖片

-ROOT-表永遠不會被分隔為多個region,保證了最多需要三次跳轉,就能定位到任意的region。client會講查詢的位置信息保存緩存起來,緩存不會主動失效,因此如果client上的緩存全部失效,則需要進行6次網絡來回,才能定位到正確的region,其中蠶絲用來發現緩存失效,另外三次用來獲取位置信息。

Store

每一個region有一個或多個store組成,至少是一個store,hbase會把一起訪問的數據放在一個store裏面,即為每個ColumnFamily建一個store,如果有幾個ColumnFamily,也就有幾個Store。一個Store由一個memStore和0或者多個StoreFile組成。

HBase以store的大小來判斷是否需要切分region。

MemStore

memStore 是放在內存裏的。保存修改的數據即keyValues。當memStore的大小達到一個閥值(默認64MB)時,memStore會被flush到文件,即生成一個快照。目前hbase 會有一個線程來負責memStore的flush操作。

StoreFile

memStore內存中的數據寫到文件後就是StoreFile,StoreFile底層是以HFile的格式保存。

HFile

HBase中KeyValue數據的存儲格式,是hadoop的二進制格式文件。

首先HFile文件是不定長的,長度固定的只有其中的兩塊:Trailer和FileInfo。Trailer中又指針指向其他數據塊的起始點,FileInfo記錄了文件的一些meta信息。

Data Block是hbase io的基本單元,為了提高效率,HRegionServer中又基於LRU的block cache機制。每個Data塊的大小可以在創建一個Table的時候通過參數指定(默認塊大小64KB),大號的Block有利於順序Scan,小號的Block利於隨機查詢。每個Data塊除了開頭的Magic以外就是一個個KeyValue對拼接而成,Magic內容就是一些隨機數字,目的是煩著數據損壞,結構如下。

技術分享圖片

HFile結構圖如下:

技術分享圖片

Data Block段用來保存表中的數據,這部分可以被壓縮。

Meta Block段(可選的)用來保存用戶自定義的kv段,可以被壓縮。

FileInfo段用來保存HFile的元信息,本能被壓縮,用戶也可以在這一部分添加自己的元信息。

Data Block Index段(可選的)用來保存Meta Blcok的索引。

Trailer這一段是定長的。保存了每一段的偏移量,讀取一個HFile時,會首先讀取Trailer,Trailer保存了每個段的起始位置(段的Magic Number用來做安全check),然後,DataBlock Index會被讀取到內存中,這樣,當檢索某個key時,不需要掃描整個HFile,而只需從內存中找到key所在的block,通過一次磁盤io將整個 block讀取到內存中,再找到需要的key。DataBlock Index采用LRU機制淘汰。

HFile的Data Block,Meta Block通常采用壓縮方式存儲,壓縮之後可以大大減少網絡IO和磁盤IO,隨之而來的開銷當然是需要花費cpu進行壓縮和解壓縮。目標HFile的壓縮支持兩種方式:gzip、lzo。

技術分享圖片

另外,針對目前針對現有HFile的兩個主要缺陷:

  • a) 暫用過多內存
  • b) 啟動加載時間緩慢

提出了HFile Version2設計:https://issues.apache.org/jira/secure/attachment/12478329/hfile_format_v2_design_draft_0.1.pdf

HLog

其實HLog文件就是一個普通的Hadoop Sequence File, Sequence File的value是key時HLogKey對象,其中記錄了寫入數據的歸屬信息,除了table和region名字外,還同時包括sequence number和timestamp,timestamp是寫入時間,equence number的起始值為0,或者是最近一次存入文件系統中的equence number。

Sequence File的value是HBase的KeyValue對象,即對應HFile中的KeyValue。

技術分享圖片

HLog(WAL log):WAL意為write ahead log,用來做災難恢復使用,HLog記錄數據的所有變更,一旦region server 宕機,就可以從log中進行恢復。

技術分享圖片

LogFlusher

前面提到,數據以KeyValue形式到達HRegionServer,將寫入WAL,之後,寫入一個SequenceFile。看過去沒問題,但是因為數據流在寫入文件系統時,經常會緩存以提高性能。這樣,有些本以為在日誌文件中的數據實際在內存中。這裏,我們提供了一個LogFlusher的類。它調用HLog.optionalSync(),後者根據hbase.regionserver.optionallogflushinterval (默認是10秒),定期調用Hlog.sync()。另外,HLog.doWrite()也會根據 hbase.regionserver.flushlogentries (默認100秒)定期調用Hlog.sync()。Sync() 本身調用HLog.Writer.sync(),它由SequenceFileLogWriter實現。

LogRoller

Log的大小通過$HBASE_HOME/conf/hbase-site.xml 的 hbase.regionserver.logroll.period 限制,默認是一個小時。所以每60分鐘,會打開一個新的log文件。久而久之,會有一大堆的文件需要維護。首先,LogRoller調用HLog.rollWriter(),定時滾動日誌,之後,利用HLog.cleanOldLogs()可以清除舊的日誌。它首先取得存儲文件中的最大的sequence number,之後檢查是否存在一個log所有的條目的“sequence number”均低於這個值,如果存在,將刪除這個log。

每個region server維護一個HLog,而不是每一個region一個,這樣不同region(來自不同的table)的日誌會混在一起,這樣做的目的是不斷追加單個文件相對於同時寫多個文件而言,可以減少磁盤尋址次數,因此可以提高table的寫性能。帶來麻煩的時,如果一個region server下線,為了恢復其上的region,需要講region server上的log進行拆分,然後分發到其他region server上進行恢復。

hbase 文件組織方式 和 多級索引機制