一文弄懂Hbase基本架構

1、存儲模型

在這裏插入圖片描述

  • table中的所有行都按照row key的字典序排列。
  • table在行的方向上分割爲多個HRegion,每個HRegion分散在不同的RegionServer中。
  • 每個HRegion由多個Store構成(每個表一開始只有一個region,隨着數據不斷插入表,region不斷增大,當增大到一個閥值的時候(依據store的大小判斷,默認初次分割閾值爲128M,詳細分割策略見:https://blog.csdn.net/jiangmingzhi23/article/details/78609864),HRegion就會等分會兩個新的HRegion),每個Store由一個MemStore和零個或多個StoreFile組成,每個Store保存一個Columns Family中
  • StoreFile以HFile格式存儲在HDFS中。
  • HRegion是Hbase中分佈式存儲和負載均衡的最小單元。最小單元就表示不同的HRegion可以分佈在不同的HRegion server上。但一個HRegion是不會拆分到多個server上的(即一個HRegion不會跨server調度和存儲)。
  • HRegion雖然是分佈式存儲的最小單元,但並不是存儲的最小單元(Data Block是HBase的最小存儲單元,一個Data Block由一個魔數和一系列的KeyValue(Cell)組成,魔數是一個隨機的數字,用於表示這是一個Data Block類型,以快速監測這個Data Block的格式,防止數據的破壞。)。

注: 一張hbase表在剛剛創建的時候,默認只有一個region。所以多有關於這張表的請求都被路由到同一個region server,不管集羣中有多少region server。這也就是爲什麼hbase表在剛剛創建的階段不能充分利用整個集羣的吞吐量的原因。如果想開始就用到集羣的吞吐量,可以再創建表時候,啓用預分區方式實現。

2、架構模型圖

在這裏插入圖片描述

  • Client
    首先當一個請求產生時,HBase Client使用RPC(遠程過程調用)機制與HMaster和HRegionServer進行通信,對於管理類操作,Client與HMaster進行RPC;對於數據讀寫操作,Client與HRegionServer進行RPC。

  • Zookeeper
    HBase Client使用RPC(遠程過程調用)機制與HMaster和HRegionServer進行通信,但如何尋址呢?由於Zookeeper中存儲了-ROOT-表的地址和HMaster的地址,所以需要先到Zookeeper上進行尋址。
    HRegionServer也會把自己以Ephemeral方式註冊到Zookeeper中,使HMaster可以隨時感知到各個HRegionServer的健康狀態。此外,Zookeeper也避免了HMaster的單點故障。

  • HMaster
    當用戶需要進行Table和Region的管理工作時,就需要和HMaster進行通信。HBase中可以啓動多個HMaster,通過Zookeeper的Master Eletion機制保證總有一個Master運行。
    管理用戶對Table的增刪改查操作
    管理HRegionServer的負載均衡,調整Region的分佈
    在Region Split後,負責新Region的分配
    在HRegionServer停機後,負責失效HRegionServer上的Regions遷移

  • HRegionServer
    當用戶需要對數據進行讀寫操作時,需要訪問HRegionServer。HRegionServer存取一個子表時,會創建一個HRegion對象,然後對錶的每個列族創建一個Store實例,每個Store都會有一個 MemStore和0個或多個StoreFile與之對應,每個StoreFile都會對應一個HFile, HFile就是實際的存儲文件。因此,一個HRegion有多少個列族就有多少個Store。 一個HRegionServer會有多個HRegion和一個HLog。

注: HStore存儲由兩部分組成:MemStore和StoreFiles。 MemStore是Sorted Memory Buffer,用戶 寫入數據首先 會放在MemStore,當MemStore滿了以後會Flush成一個 StoreFile(實際存儲在HDHS上的是HFile),當StoreFile文件數量增長到一定閥值,就會觸發Compact合併操作,並將多個StoreFile合併成一個StoreFile,合併過程中會進行版本合併和數據刪除,因此可以看出HBase其實只有增加數據,所有的更新和刪除操作都是在後續的compact過程中進行的,這使得用戶的 讀寫操作*只要進入內存中就可以立即返回,保證了HBase I/O的高性能。

3、ROOT表和META表

HBase的用-ROOT-表來記錄.META.的Region信息,就和.META.記錄用戶表的Region信息一模一樣。-ROOT-只會有一個Region。
這麼一來Client端就需要先去訪問-ROOT-表。所以需要知道管理-ROOT-表的RegionServer的地址。這個地址被存在ZooKeeper中。默認的路徑是: /hbase/root-region-server
-ROOT-行記錄結構
在這裏插入圖片描述
.META.表結構
在這裏插入圖片描述
HBase的所有Region元數據被存儲在.META.表中,隨着Region的增多,.META.表中的數據也會增大,並分裂成多個新的Region。爲了定位.META.表中各個Region的位置,把.META.表中所有Region的元數據保存在-ROOT-表中,最後由Zookeeper記錄-ROOT-表的位置信息。所有客戶端訪問用戶數據前,需要首先訪問Zookeeper獲得-ROOT-的位置,然後訪問-ROOT-表獲得.META.表的位置,最後根據.META.表中的信息確定用戶數據存放的位置,如下圖所示。
在這裏插入圖片描述
-ROOT-表永遠不會被分割,它只有一個Region,這樣可以保證最多隻需要三次跳轉就可以定位任意一個Region。爲了加快訪問速度,.META.表的所有Region全部保存在內存中。客戶端會將查詢過的位置信息緩存起來,且緩存不會主動失效。如果客戶端根據緩存信息還訪問不到數據,則詢問相關.META.表的Region服務器,試圖獲取數據的位置,如果還是失敗,則詢問-ROOT-表相關的.META.表在哪裏。最後,如果前面的信息全部失效,則通過ZooKeeper重新定位Region的信息。所以如果客戶端上的緩存全部是失效,則需要進行6次網絡來回,才能定位到正確的Region。
最後要提醒大家注意兩件事情:

  1. 在整個路由過程中並沒有涉及到MasterServer,也就是說HBase日常的數據操作並不需要MasterServer,不會造成MasterServer的負擔。
  2. Client端並不會每次數據操作都做這整個路由過程,很多數據都會被Cache起來。至於如何Cache,則不在本文的討論範圍之內。

參考:
https://www.cnblogs.com/csyuan/p/6543018.html
https://blog.csdn.net/ldds_520/article/details/51674315
https://blog.csdn.net/yyl424525/article/details/77505749

4、Region拆分原理

參考:https://blog.csdn.net/jiangmingzhi23/article/details/78609864
寫請求被region server處理,region server會先將數據寫到稱爲“memstore”的內存存儲系統中。一旦memstore寫滿,就會被寫到磁盤上的存儲文件中,這個過程稱爲“memstore flush”。隨着存儲文件的積累,region server會將它們合併成一個更大文件。隨着每一次寫磁盤和合並操作完成,如果region拆分策略任務這個region需要被拆分,則會發起region拆分請求。由於hbase所有的數據文件是不可變的,進行region拆分時,一個region被拆分爲兩個region時,兩個新創建的region不會重寫所有的數據到新的文件,而是創建小的sym-link文件,sym-link文件也叫reference文件。reference文件根據分割點,指向父存儲文件的頂部或底部。reference文件的使用和常規數據文件一樣,但它只有一半的記錄。如果reference文件不再有對父region的不可變數據文件的引用,則這個region不可以再拆分。這些reference文件通過合併逐漸清理,以便該region停止引用其父文件,並可以進一步拆分。
儘管region拆分是由region server本地進行決策的,但是拆分過程卻有很多參與者。region server在region拆分前後都會通知Master進程更新.META.表, 以便client可以找到拆分出來的新的兩個region。還需要重新排列目錄結構以及HDFS中的數據文件。region拆分過程有多個任務完成。爲了在發生錯誤時可以回滾,regionserver會在內存中保存執行狀態日誌。圖1顯示了Region Server執行拆分的步驟。每個步驟都標有其步驟編號。來自Region Servers或Master的操作顯示爲紅色,而來自客戶端的操作顯示爲綠色。
在這裏插入圖片描述

  • 1.region server自身決定region拆分,並準備發起拆分。作爲第一步,它將在zookeeper的分區/hbase/region-in-transition/region-name下中創建一個znode。
  • 2.因爲Master是父region-in-transition的znode節點的觀察者,所以它知曉這個znode的建立。
  • 3.region server在HDFS的父region目錄下創建一個名爲“.splits”的子目錄。
  • 4.region server關閉父region,強制cache刷盤並在本地數據結構中將這個region標記爲offline。此時,父region的client請求將拋出NotServingRegionException,client將重試。
  • 5.region server爲子region A和B分別在.splits目錄下的region目錄,並創建必要的數據結構。然後拆分存儲文件,即先在父region中創建每個存儲文件兩個reference文件。這兩個reference文件將指向父region文件。
  • 6.region server在HDFS中創建實際的region目錄,併爲每個子region更新相應的reference文件。
  • 7.region server發起Put請求到.META.表,並在.META.表中將父region設置爲offline,表並添加有關子region的信息。此時,.META.表中不會有每個子region的單獨的條目。client可以通過scan .META.表來知曉父region正在拆分,但是除非子region信息記錄到.META.表,否則client是看不到子region的。如果前面的Put操作成功寫入到.META.表,則標誌父region拆分完成。如果region server在put操作前返回失敗,則Master和打開這個region的region server將會清除region拆分的錯誤狀態,如果.META.表成功更新,則region拆分狀態會被Master向前翻。
  • 8.region server打開子region並行地接受寫入請求。
  • 9.region server將子region A和B,以及它們的承載者信息分別添加到.META.表。之後,client就可以發現新的region,並訪問之。client本地緩存.META.表信息,但是當它們訪問region server或者.MET.表時,本地緩存失效,client從.META.表獲取新的region信息。
  • 10.region server更新zookeeper的/hbase/region-in-transition/region-name節點中的region狀態到SPLIT,以便master感知其狀態變化。如果需要的話,負載器可以將子region自由地指定到其它region。
  • 11.region拆分完成後,其元數據和HDFS仍將包含對父region的引用。這些引用將在子region壓縮重寫數據文件時被刪除。Master的GC任務會定期檢查子region是否仍然引用父文件,如果沒有,父region將被刪除。

5、HBase在HDFS中存儲

  • /hbase/.tmp:臨時目錄,當對錶做創建和刪除的時候,會將表move到該目錄,然後進行操作
  • /hbase/data:核心目錄,存儲HBase表的數據 默認情況下,目錄下有兩個目錄
  • /hbase/data/default: 在用戶創建表的時候,沒有指定namespace時,表就創建在此目錄下
  • /hbase/data/hbase:系統內部創建的表,.META.表(region的詳細信息)和namespace表(namespace信息)
  • /hbase/hbase.id:存儲的是集羣的唯一cluster id(uuid)
  • /hbase/hbase.version:集羣的版本號
  • /hbase/oldWALs: 對應0.94.x版本中.oldlogs目錄 當/hbase/WALs目錄中的logs沒有之後,會將這些logs移動到此目錄下,HMaster會定期清理

參考:
http://dxer.github.io/2016/03/19/hbase%E7%AE%80%E4%BB%8B/

6、讀寫操作流程

寫操作流程

(1) Client通過Zookeeper的調度,向RegionServer發出寫數據請求,在Region中寫數據。
(2) 數據被寫入Region的MemStore,直到MemStore達到預設閾值。
(3) MemStore中的數據被Flush成一個StoreFile。
(4) 隨着StoreFile文件的不斷增多,當其數量增長到一定閾值後,觸發Compact合併操作,將多個StoreFile合併成一個StoreFile,同時進行版本合併和數據刪除。
(5) StoreFiles通過不斷的Compact合併操作,逐步形成越來越大的StoreFile。
(6) 單個StoreFile大小超過一定閾值後,觸發Split操作,把當前Region Split成2個新的Region。父Region會下線,新Split出的2個子Region會被HMaster分配到相應的RegionServer上,使得原先1個Region的壓力得以分流到2個Region上。
可以看出HBase只有增添數據,所有的更新和刪除操作都是在後續的Compact歷程中舉行的,使得用戶的寫操作只要進入內存就可以立刻返回,實現了HBase I/O的高性能。

讀操作流程

(1) Client訪問Zookeeper,查找-ROOT-表,獲取.META.表信息。
(2) 從.META.表查找,獲取存放目標數據的Region信息,從而找到對應的RegionServer。
(3) 通過RegionServer獲取需要查找的數據。
(4) Regionserver的內存分爲MemStore和BlockCache兩部分,MemStore主要用於寫數據,BlockCache主要用於讀數據。讀請求先到MemStore中查數據,查不到就到BlockCache中查,再查不到就會到StoreFile上讀,並把讀的結果放入BlockCache。
尋址過程:client–>Zookeeper–>-ROOT-表–>META表–>RegionServer–>Region–>client

7、Hbase的容錯性

  • Master容錯:Zookeeper重新選擇一個新的Master
    (1)無Master過程中,數據讀取仍照常進行;
    (2)無master過程中,region切分、負載均衡等無法進行;
  • RegionServer容錯:定時向Zookeeper彙報心跳,如果一旦時間內未出現心跳,Master將該RegionServer上的Region重新分配到其他RegionServer上,失效服務器上“預寫”日誌由主服務器進行分割並派送給新的RegionServer
  • Zookeeper容錯:Zookeeper是一個可靠地服務,一般配置3或5個Zookeeper實例
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章