歡迎你們前往騰訊雲技術社區,獲取更多騰訊海量技術實踐乾貨哦~java
做者:張秀雲 node
最近在跟進Hbase的相關工做,因爲以前對Hbase並不怎麼了解,所以系統地學習了下Hbase,爲了加深對Hbase的理解,對相關知識點作了筆記,並在組內進行了Hbase相關技術的分享,因爲Hbase涵蓋的內容比較多,所以計劃分享2期,下面就是針對第一期Hbase技術分享總體而成,第一期的主要內容以下:mysql
1、Hbase介紹
2、Hbase的Region介紹
3、Hbase的寫邏輯介紹
4、Hbase的故障恢復
5、Hbase的拆分和合並sql
以下ppt所示:shell
下面就來針對各個部分的內容來進行詳細的介紹:數據庫
Hbase是Hadoop Database的簡稱 ,Hbase項目是由Powerset公司的Chad Walters和Jim Kelleman在2006年底發起,根據Google的Chang等人發表的論文「Bigtable:A Distributed Storage System for Strctured Data「來設計的。2007年10月發佈了第一個版本。2010年5月,Hbase從Hadoop子項目升級成Apache頂級項目。後端
Hbase是分佈式、面向列的開源數據庫(其實準確的說是面向列族)。HDFS爲Hbase提供可靠的底層數據存儲服務,MapReduce爲Hbase提供高性能的計算能力,Zookeeper爲Hbase提供穩定服務和Failover機制,所以咱們說Hbase是一個經過大量廉價的機器解決海量數據的高速存儲和讀取的分佈式數據庫解決方案。api
提煉出Hbase的幾個特色,以下圖所示:緩存
2.一、海量存儲安全
Hbase適合存儲PB級別的海量數據,在PB級別的數據以及採用廉價PC存儲的狀況下,能在幾十到百毫秒內返回數據。這與Hbase的極易擴展性息息相關。正式由於Hbase良好的擴展性,才爲海量數據的存儲提供了便利。
2.二、列式存儲
這裏的列式存儲其實說的是列族存儲,Hbase是根據列族來存儲數據的。列族下面能夠有很是多的列,列族在建立表的時候就必須指定。爲了加深對Hbase列族的理解,下面是一個簡單的關係型數據庫的表和Hbase數據庫的表:
RDBMS的表:
Hbase的表:
下圖是針對Hbase和關係型數據庫的基本的一個比較:
2.三、極易擴展
Hbase的擴展性主要體如今兩個方面,一個是基於上層處理能力(RegionServer)的擴展,一個是基於存儲的擴展(HDFS)。
經過橫向添加RegionSever的機器,進行水平擴展,提高Hbase上層的處理能力,提高Hbsae服務更多Region的能力。
備註:RegionServer的做用是管理region、承接業務的訪問,這個後面會詳細的介紹經過橫向添加Datanode的機器,進行存儲層擴容,提高Hbase的數據存儲能力和提高後端存儲的讀寫能力。
2.四、高併發
因爲目前大部分使用Hbase的架構,都是採用的廉價PC,所以單個IO的延遲其實並不小,通常在幾十到上百ms之間。這裏說的高併發,主要是在併發的狀況下,Hbase的單個IO延遲降低並很少。能得到高併發、低延遲的服務。
2.五、稀疏
稀疏主要是針對Hbase列的靈活性,在列族中,你能夠指定任意多的列,在列數據爲空的狀況下,是不會佔用存儲空間的。
在我學習Hbase的時候有幾個概念須要重點理解一下,列出4個基礎概念以下圖所示:
3.一、Column Family的概念
Column Family又叫列族,Hbase經過列族劃分數據的存儲,列族下面能夠包含任意多的列,實現靈活的數據存取。剛接觸的時候,理解起來有點吃力。我想到了一個很是相似的概念,理解起來就很是容易了。那就是家族的概念,咱們知道一個家族是因爲不少個的家庭組成的。列族也相似,列族是由一個一個的列組成(任意多)。
Hbase表的建立的時候就必須指定列族。就像關係型數據庫建立的時候必須指定具體的列是同樣的。
Hbase的列族不是越多越好,官方推薦的是列族最好小於或者等於3。咱們使用的場景通常是1個列族。
3.二、Rowkey的概念
Rowkey的概念和mysql中的主鍵是徹底同樣的,Hbase使用Rowkey來惟一的區分某一行的數據。
因爲Hbase只支持3中查詢方式:
所以,Rowkey對Hbase的性能影響很是大,Rowkey的設計就顯得尤其的重要。設計的時候要兼顧基於Rowkey的單行查詢也要鍵入Rowkey的範圍掃描。具體Rowkey要如何設計後續會整理相關的文章作進一步的描述。這裏你們只要有一個概念就是Rowkey的設計極爲重要。
3.三、Region的概念
Region的概念和關係型數據庫的分區或者分片差很少。
Hbase會將一個大表的數據基於Rowkey的不一樣範圍分配到不通的Region中,每一個Region負責必定範圍的數據訪問和存儲。這樣即便是一張巨大的表,因爲被切割到不通的region,訪問起來的時延也很低。
3.四、TimeStamp的概念
TimeStamp對Hbase來講相當重要,由於它是實現Hbase多版本的關鍵。在Hbase中使用不一樣的timestame來標識相同rowkey行對應的不通版本的數據。
在寫入數據的時候,若是用戶沒有指定對應的timestamp,Hbase會自動添加一個timestamp,timestamp和服務器時間保持一致。
在Hbase中,相同rowkey的數據按照timestamp倒序排列。默認查詢的是最新的版本,用戶可同指定timestamp的值來讀取舊版本的數據。
Hbase的架構圖以下圖所示:
從圖中能夠看出Hbase是由Client、Zookeeper、Master、HRegionServer、HDFS等幾個組建組成,下面來介紹一下幾個組建的相關功能:
4.一、Client
Client包含了訪問Hbase的接口,另外Client還維護了對應的cache來加速Hbase的訪問,好比cache的.META.元數據的信息。
4.二、Zookeeper
Hbase經過Zookeeper來作master的高可用、RegionServer的監控、元數據的入口以及集羣配置的維護等工做。具體工做以下:
經過Zoopkeeper來保證集羣中只有1個master在運行,若是master異常,會經過競爭機制產生新的master提供服務
經過Zoopkeeper來監控RegionServer的狀態,當RegionSevrer有異常的時候,經過回調的形式通知Master RegionServer上下限的信息
經過Zoopkeeper存儲元數據的統一入口地址
4.三、Hmaster
master節點的主要職責以下:
爲RegionServer分配Region
維護整個集羣的負載均衡
維護集羣的元數據信息
發現失效的Region,並將失效的Region分配到正常的RegionServer上
當RegionSever失效的時候,協調對應Hlog的拆分
4.四、HregionServer
HregionServer直接對接用戶的讀寫請求,是真正的「幹活」的節點。它的功能歸納以下:
管理master爲其分配的Region
處理來自客戶端的讀寫請求
負責和底層HDFS的交互,存儲數據到HDFS
負責Region變大之後的拆分
負責Storefile的合併工做
4.五、HDFS
HDFS爲Hbase提供最終的底層數據存儲服務,同時爲Hbase提供高可用(Hlog存儲在HDFS)的支持,具體功能歸納以下:
提供元數據和表數據的底層分佈式存儲服務
數據多副本,保證的高可靠和高可用性
Hbase是一個經過廉價PC機器集羣來存儲海量數據的分佈式數據庫解決方案。它比較適合的場景歸納以下:
有幾個典型的場景特別適合使用Hbase來存儲:
海量訂單流水數據(長久保存)
交易記錄
數據庫歷史數據
前面已經介紹了Region相似於數據庫的分片和分區的概念,每一個Region負責一小部分Rowkey範圍的數據的讀寫和維護,Region包含了對應的起始行到結束行的全部信息。master將對應的region分配給不一樣的RergionServer,由RegionSever來提供Region的讀寫服務和相關的管理工做。這部分主要介紹Region實例以及Rgeion的尋找路徑:
上圖模擬了一個Hbase的表是如何拆分紅region,以及分配到不一樣的RegionServer中去。上面是1個Userinfo表,裏面有7條記錄,其中rowkey爲0001到0002的記錄被分配到了Region1上,Rowkey爲0003到0004的記錄被分配到了Region2上,而rowkey爲000五、0006和0007的記錄則被分配到了Region3上。region1和region2被master分配給了RegionServer1(RS1),Region3被master配分給了RegionServer2(RS2)
備註:這裏只是爲了更容易的說明拆分的規則,其實真實的場景並不會幾條記錄拆分到不通的Region上,而是到必定的數據量纔會拆分,具體的在Region的拆分那部分再具體的介紹。
既然讀寫都在RegionServer上發生,咱們前面有講到,每一個RegionSever爲必定數量的region服務,那麼client要對某一行數據作讀寫的時候如何能知道具體要去訪問哪一個RegionServer呢?那就是接下來咱們要討論的問題
2.一、老的Region尋址方式
在Hbase 0.96版本之前,Hbase有兩個特殊的表,分別是-ROOT-表和.META.表,其中-ROOT-的位置存儲在ZooKeeper中,-ROOT-自己存儲了 .META. Table的RegionInfo信息,而且-ROOT-不會分裂,只有一個region。而.META.表能夠被切分紅多個region。讀取的流程以下圖所示:
第1步:client請求ZK得到-ROOT-所在的RegionServer地址
第2步:client請求-ROOT-所在的RS地址,獲取.META.表的地址,client會將-ROOT-的相關信息cache下來,以便下一次快速訪問
第3步:client請求 .META.表的RS地址,獲取訪問數據所在RegionServer的地址,client會將.META.的相關信息cache下來,以便下一次快速訪問
第4步:client請求訪問數據所在RegionServer的地址,獲取對應的數據
從上面的路徑咱們能夠看出,用戶須要3次請求才能直到用戶Table真正的位置,這在必定程序帶來了性能的降低。在0.96以前使用3層設計的主要緣由是考慮到元數據可能須要很大。可是真正集羣運行,元數據的大小其實很容易計算出來。在BigTable的論文中,每行METADATA數據存儲大小爲1KB左右,若是按照一個Region爲128M的計算,3層設計能夠支持的Region個數爲2^34個,採用2層設計能夠支持2^17(131072)。那麼2層設計的狀況下一個 集羣能夠存儲4P的數據。這僅僅是一個Region只有128M的狀況下。若是是10G呢? 所以,經過計算,其實2層設計就能夠知足集羣的需求。所以在0.96版本之後就去掉了-ROOT-表了。
2.二、新的Region尋址方式
如上面的計算,2層結構其實徹底能知足業務的需求,所以0.96版本之後將-ROOT-表去掉了。以下圖所示:
訪問路徑變成了3步:
第1步:Client請求ZK獲取.META.所在的RegionServer的地址。
第2步:Client請求.META.所在的RegionServer獲取訪問數據所在的RegionServer地址,client會將.META.的相關信息cache下來,以便下一次快速訪問。
第3步:Client請求數據所在的RegionServer,獲取所須要的數據。
總結去掉-ROOT-的緣由有以下2點:
其一:提升性能
其二:2層結構已經足以知足集羣的需求
這裏還有一個問題須要說明,那就是Client會緩存.META.的數據,用來加快訪問,既然有緩存,那它何時更新?若是.META.更新了,好比Region1不在RerverServer2上了,被轉移到了RerverServer3上。client的緩存沒有更新會有什麼狀況?
其實,Client的元數據緩存不更新,當.META.的數據發生更新。如上面的例子,因爲Region1的位置發生了變化,Client再次根據緩存去訪問的時候,會出現錯誤,當出現異常達到重試次數後就會去.META.所在的RegionServer獲取最新的數據,若是.META.所在的RegionServer也變了,Client就會去ZK上獲取.META.所在的RegionServer的最新地址。
Hbase的寫邏輯涉及到寫內存、寫log、刷盤等操做,看起來簡單,其實裏面又有不少的邏輯,下面就來作詳細的介紹
Hbase的寫入流程以下圖所示:
從上圖能夠看出氛圍3步驟:
第1步:Client獲取數據寫入的Region所在的RegionServer
第2步:請求寫Hlog
第3步:請求寫MemStore
只有當寫Hlog和寫MemStore都成功了纔算請求寫入完成。MemStore後續會逐漸刷到HDFS中。
備註:Hlog存儲在HDFS,當RegionServer出現異常,須要使用Hlog來恢復數據。
爲了提升Hbase的寫入性能,當寫請求寫入MemStore後,不會當即刷盤。而是會等到必定的時候進行刷盤的操做。具體是哪些場景會觸發刷盤的操做呢?總結成以下的幾個場景:
2.一、全局內存控制
這個全局的參數是控制內存總體的使用狀況,當全部memstore佔整個heap的最大比例的時候,會觸發刷盤的操做。這個參數是hbase.regionserver.global.memstore.upperLimit,默認爲整個heap內存的40%。但這並不意味着全局內存觸發的刷盤操做會將全部的MemStore都進行輸盤,而是經過另一個參數hbase.regionserver.global.memstore.lowerLimit來控制,默認是整個heap內存的35%。當flush到全部memstore佔整個heap內存的比率爲35%的時候,就中止刷盤。這麼作主要是爲了減小刷盤對業務帶來的影響,實現平滑系統負載的目的。
2.二、MemStore達到上限
當MemStore的大小達到hbase.hregion.memstore.flush.size大小的時候會觸發刷盤,默認128M大小
2.三、RegionServer的Hlog數量達到上限
前面說到Hlog爲了保證Hbase數據的一致性,那麼若是Hlog太多的話,會致使故障恢復的時間太長,所以Hbase會對Hlog的最大個數作限制。當達到Hlog的最大個數的時候,會強制刷盤。這個參數是hase.regionserver.max.logs,默認是32個。
2.四、手工觸發
能夠經過hbase shell或者java api手工觸發flush的操做。
2.五、關閉RegionServer觸發
在正常關閉RegionServer會觸發刷盤的操做,所有數據刷盤後就不須要再使用Hlog恢復數據。
2.六、Region使用HLOG恢復完數據後觸發
當RegionServer出現故障的時候,其上面的Region會遷移到其餘正常的RegionServer上,在恢復完Region的數據後,會觸發刷盤,當刷盤完成後纔會提供給業務訪問。
3.一、Hlog簡介
Hlog是Hbase實現WAL(Write ahead log)方式產生的日誌信息,內部是一個簡單的順序日誌。每一個RegionServer對應1個Hlog(備註:1.x版本的能夠開啓MultiWAL功能,容許多個Hlog),全部對於該RegionServer的寫入都被記錄到Hlog中。Hlog實現的功能就是咱們前面講到的保證數據安全。當RegionServer出現問題的時候,能跟進Hlog來作數據恢復。此外爲了保證恢復的效率,Hbase會限制最大保存的Hlog數量,若是達到Hlog的最大個數(hase.regionserver.max.logs參數控制)的時候,就會觸發強制刷盤操做。對於已經刷盤的數據,其對應的Hlog會有一個過時的概念,Hlog過時後,會被監控線程移動到 .oldlogs,而後會被自動刪除掉。
Hbase是如何判斷Hlog過時的呢?要找到這個答案,咱們就必須瞭解Hlog的詳細結構。
3.二、Hlog結構
下圖是Hlog的詳細結構(圖片來源 http://hbasefly.com/ ):
從上圖咱們能夠看出都個Region共享一個Hlog文件,單個Region在Hlog中是按照時間順序存儲的,可是多個Region可能並非徹底按照時間順序。
每一個Hlog最小單元由Hlogkey和WALEdit兩部分組成。Hlogky由sequenceid、timestamp、cluster ids、regionname以及tablename等組成,WALEdit是由一系列的KeyValue組成,對一行上全部列(即全部KeyValue)的更新操做,都包含在同一個WALEdit對象中,這主要是爲了實現寫入一行多個列時的原子性。
注意,圖中有個sequenceid的東東。sequenceid是一個store級別的自增序列號,這東東很是重要,region的數據恢復和Hlog過時清除都要依賴這個東東。下面就來簡單描述一下sequenceid的相關邏輯。
3.三、Hlog的生命週期
Hlog從產生到最後刪除須要經歷以下幾個過程:
產生
全部涉及到數據的變動都會先寫Hlog,除非是你關閉了Hlog
滾動
Hlog的大小經過參數hbase.regionserver.logroll.period控制,默認是1個小時,時間達到hbase.regionserver.logroll.period 設置的時間,Hbase會建立一個新的Hlog文件。這就實現了Hlog滾動的目的。Hbase經過hbase.regionserver.maxlogs參數控制Hlog的個數。滾動的目的,爲了控制單個Hlog文件過大的狀況,方便後續的過時和刪除。
過時
前面咱們有講到sequenceid這個東東,Hlog的過時依賴於對sequenceid的判斷。Hbase會將Hlog的sequenceid和Hfile最大的sequenceid(刷新到的最新位置)進行比較,若是該Hlog文件中的sequenceid比刷新的最新位置的sequenceid都要小,那麼這個Hlog就過時了,過時了之後,對應Hlog會被移動到.oldlogs目錄。
這裏有個問題,爲何要將過時的Hlog移動到.oldlogs目錄,而不是直接刪除呢?
答案是由於Hbase還有一個主從同步的功能,這個依賴Hlog來同步Hbase的變動,有一種狀況不能刪除Hlog,那就是Hlog雖然過時,可是對應的Hlog並無同步完成,所以比較好的作好是移動到別的目錄。再增長對應的檢查和保留時間。
此文已由做者受權騰訊雲技術社區發佈,轉載請註明文章出處原文連接:https://cloud.tencent.com/community/article/761242