1. 程式人生 > >hbase學習教程(二):HBase容錯性和Hbase使用場景、Hbase讀寫過程詳解

hbase學習教程(二):HBase容錯性和Hbase使用場景、Hbase讀寫過程詳解

HBase容錯性

Write-Ahead-Log(WAL)
這裡寫圖片描述
該機制用於資料的容錯和恢復:
每個HRegionServer中都有一個HLog物件,HLog是一個實現Write Ahead Log的類,在每次使用者操作寫入MemStore的同時,也會寫一份資料到HLog檔案中(HLog檔案格式見後續),HLog檔案定期會滾動出新的,並刪除舊的檔案(已持久化到StoreFile中的資料)。當HRegionServer意外終止後,HMaster會通過Zookeeper感知到,HMaster首先會處理遺留的 HLog檔案,將其中不同Region的Log資料進行拆分,分別放到相應region的目錄下,然後再將失效的region重新分配,領取 到這些region的HRegionServer在Load Region的過程中,會發現有歷史HLog需要處理,因此會Replay HLog中的資料到MemStore中,然後flush到StoreFiles,完成資料恢復。

HBase容錯性
Master容錯:Zookeeper重新選擇一個新的Master
無Master過程中,資料讀取仍照常進行;
無master過程中,region切分、負載均衡等無法進行;
RegionServer容錯:定時向Zookeeper彙報心跳,如果一旦時間內未出現心跳,Master將該RegionServer上的Region重新分配到其他RegionServer上,失效伺服器上“預寫”日誌由主伺服器進行分割並派送給新的RegionServer
Zookeeper容錯:Zookeeper是一個可靠地服務,一般配置3或5個Zookeeper例項
Region定位流程:
這裡寫圖片描述


尋找RegionServer
ZooKeeper–> -ROOT-(單Region)–> .META.–> 使用者表

-ROOT-
表包含.META.表所在的region列表,該表只會有一個Region;
Zookeeper中記錄了-ROOT-表的location。

.META.
表包含所有的使用者空間region列表,以及RegionServer的伺服器地址。

Hbase使用場景

大資料量儲存,大資料量高併發操作
需要對資料隨機讀寫操作
讀寫訪問均是非常簡單的操作

Hbase與HDFS對比
兩者都具有良好的容錯性和擴充套件性,都可以擴充套件到成百上千個節點;
HDFS適合批處理場景
不支援資料隨機查詢
不適合增量資料處理
不支援資料更新
這裡寫圖片描述

Hbase讀寫過程詳解

HBase的第一次讀寫
在HBase 0.96以前,HBase有兩個特殊的Table:-ROOT-和.META.(如BigTable中的設計),其中-ROOT- Table的位置儲存在ZooKeeper,它儲存了.META. Table的RegionInfo資訊,並且它只能存在一個HRegion,而.META. Table則儲存了使用者Table的RegionInfo資訊,它可以被切分成多個HRegion,因而對第一次訪問使用者Table時,首先從ZooKeeper中讀取-ROOT- Table所在HRegionServer;然後從該HRegionServer中根據請求的TableName,RowKey讀取.META. Table所在HRegionServer;最後從該HRegionServer中讀取.META. Table的內容而獲取此次請求需要訪問的HRegion所在的位置,然後訪問該HRegionSever獲取請求的資料,這需要三次請求才能找到使用者Table所在的位置,然後第四次請求開始獲取真正的資料。當然為了提升效能,客戶端會快取-ROOT- Table位置以及-ROOT-/.META. Table的內容。如下圖所示:
這裡寫圖片描述

可是即使客戶端有快取,在初始階段需要三次請求才能直到使用者Table真正所在的位置也是效能低下的,而且真的有必要支援那麼多的HRegion嗎?或許對Google這樣的公司來說是需要的,但是對一般的叢集來說好像並沒有這個必要。在BigTable的論文中說,每行METADATA儲存1KB左右資料,中等大小的Tablet(HRegion)在128MB左右,3層位置的Schema設計可以支援2^34個Tablet(HRegion)。即使去掉-ROOT- Table,也還可以支援2^17(131072)個HRegion, 如果每個HRegion還是128MB,那就是16TB,這個貌似不夠大,但是現在的HRegion的最大大小都會設定的比較大,比如我們設定了2GB,此時支援的大小則變成了4PB,對一般的叢集來說已經夠了,因而在HBase 0.96以後去掉了-ROOT- Table,只剩下這個特殊的目錄表叫做Meta Table(hbase:meta),它儲存了叢集中所有使用者HRegion的位置資訊,而ZooKeeper的節點中(/hbase/meta-region-server)儲存的則直接是這個Meta Table的位置,並且這個Meta Table如以前的-ROOT- Table一樣是不可split的。這樣,客戶端在第一次訪問使用者Table的流程就變成了:
1.從ZooKeeper(/hbase/meta-region-server)中獲取hbase:meta的位置(HRegionServer的位置),快取該位置資訊。
2.從HRegionServer中查詢使用者Table對應請求的RowKey所在的HRegionServer,快取該位置資訊。
3.從查詢到HRegionServer中讀取Row。
從這個過程中,我們發現客戶會快取這些位置資訊,然而第二步它只是快取當前RowKey對應的HRegion的位置,因而如果下一個要查的RowKey不在同一個HRegion中,則需要繼續查詢hbase:meta所在的HRegion,然而隨著時間的推移,客戶端快取的位置資訊越來越多,以至於不需要再次查詢hbase:meta Table的資訊,除非某個HRegion因為宕機或Split被移動,此時需要重新查詢並且更新快取。
這裡寫圖片描述

hbase:meta表
hbase:meta表儲存了所有使用者HRegion的位置資訊,它的RowKey是:tableName,regionStartKey,regionId,replicaId等,它只有info列族,這個列族包含三個列,他們分別是:info:regioninfo列是RegionInfo的proto格式:regionId,tableName,startKey,endKey,offline,split,replicaId;info:server格式:HRegionServer對應的server:port;info:serverstartcode格式是HRegionServer的啟動時間戳。
這裡寫圖片描述

HRegionServer詳解
HRegionServer一般和DataNode在同一臺機器上執行,實現資料的本地性。HRegionServer包含多個HRegion,由WAL(HLog)、BlockCache、MemStore、HFile組成。

1.WAL即Write Ahead Log,在早期版本中稱為HLog,它是HDFS上的一個檔案,如其名字所表示的,所有寫操作都會先保證將資料寫入這個Log檔案後,才會真正更新MemStore,最後寫入HFile中。採用這種模式,可以保證HRegionServer宕機後,我們依然可以從該Log檔案中讀取資料,Replay所有的操作,而不至於資料丟失。這個Log檔案會定期Roll出新的檔案而刪除舊的檔案(那些已持久化到HFile中的Log可以刪除)。WAL檔案儲存在/hbase/WALs/${HRegionServer_Name}的目錄中(在0.94之前,儲存在/hbase/.logs/目錄中),一般一個HRegionServer只有一個WAL例項,也就是說一個HRegionServer的所有WAL寫都是序列的(就像log4j的日誌寫也是序列的),這當然會引起效能問題,因而在HBase 1.0之後,通過HBASE-5699實現了多個WAL並行寫(MultiWAL),該實現採用HDFS的多個管道寫,以單個HRegion為單位。關於WAL可以參考Wikipedia的Write-Ahead Logging。順便吐槽一句,英文版的維基百科竟然能毫無壓力的正常訪問了,這是某個GFW的疏忽還是以後的常態?

2.BlockCache是一個讀快取,即“引用區域性性”原理(也應用於CPU,分空間區域性性和時間區域性性,空間區域性性是指CPU在某一時刻需要某個資料,那麼有很大的概率在一下時刻它需要的資料在其附近;時間區域性性是指某個資料在被訪問過一次後,它有很大的概率在不久的將來會被再次的訪問),將資料預讀取到記憶體中,以提升讀的效能。HBase中提供兩種BlockCache的實現:預設on-heap LruBlockCache和BucketCache(通常是off-heap)。通常BucketCache的效能要差於LruBlockCache,然而由於GC的影響,LruBlockCache的延遲會變的不穩定,而BucketCache由於是自己管理BlockCache,而不需要GC,因而它的延遲通常比較穩定,這也是有些時候需要選用BucketCache的原因。這篇文章BlockCache101對on-heap和off-heap的BlockCache做了詳細的比較。

3.HRegion是一個Table中的一個Region在一個HRegionServer中的表達。一個Table可以有一個或多個Region,他們可以在一個相同的HRegionServer上,也可以分佈在不同的HRegionServer上,一個HRegionServer可以有多個HRegion,他們分別屬於不同的Table。HRegion由多個Store(HStore)構成,每個HStore對應了一個Table在這個HRegion中的一個Column Family,即每個Column Family就是一個集中的儲存單元,因而最好將具有相近IO特性的Column儲存在一個Column Family,以實現高效讀取(資料區域性性原理,可以提高快取的命中率)。HStore是HBase中儲存的核心,它實現了讀寫HDFS功能,一個HStore由一個MemStore 和0個或多個StoreFile組成。

(1).MemStore是一個寫快取(In Memory Sorted Buffer),所有資料的寫在完成WAL日誌寫後,會 寫入MemStore中,由MemStore根據一定的演算法將資料Flush到地層HDFS檔案中(HFile),通常每個HRegion中的每個 Column Family有一個自己的MemStore。

(2).HFile(StoreFile) 用於儲存HBase的資料(Cell/KeyValue)。在HFile中的資料是按RowKey、Column Family、Column排序,對相同的Cell(即這三個值都一樣),則按timestamp倒序排列。
這裡寫圖片描述
雖然上面這張圖展現的是最新的HRegionServer的架構(但是並不是那麼的精確),但是我一直比較喜歡看以下這張圖,即使它展現的應該是0.94以前的架構。
這裡寫圖片描述

HRegionServer中資料寫流程圖解
當客戶端發起一個Put請求時,首先它從hbase:meta表中查出該Put資料最終需要去的HRegionServer。然後客戶端將Put請求傳送給相應的HRegionServer,在HRegionServer中它首先會將該Put操作寫入WAL日誌檔案中(Flush到磁碟中)。
這裡寫圖片描述

寫完WAL日誌檔案後,HRegionServer根據Put中的TableName和RowKey找到對應的HRegion,並根據Column Family找到對應的HStore,並將Put寫入到該HStore的MemStore中。此時寫成功,並返回通知客戶端。
這裡寫圖片描述

MemStore Flush
MemStore是一個In Memory Sorted Buffer,在每個HStore中都有一個MemStore,即它是一個HRegion的一個Column Family對應一個例項。它的排列順序以RowKey、Column Family、Column的順序以及Timestamp的倒序,如下所示:
這裡寫圖片描述

每一次Put/Delete請求都是先寫入到MemStore中,當MemStore滿後會Flush成一個新的StoreFile(底層實現是HFile),即一個HStore(Column Family)可以有0個或多個StoreFile(HFile)。有以下三種情況可以觸發MemStore的Flush動作,需要注意的是MemStore的最小Flush單元是HRegion而不是單個MemStore。據說這是Column Family有個數限制的其中一個原因,估計是因為太多的Column Family一起Flush會引起效能問題?具體原因有待考證。

1.當一個HRegion中的所有MemStore的大小總和超過了hbase.hregion.memstore.flush.size的大小,預設128MB。此時當前的HRegion中所有的MemStore會Flush到HDFS中。

2.當全域性MemStore的大小超過了hbase.regionserver.global.memstore.upperLimit的大小,預設40%的記憶體使用量。此時當前HRegionServer中所有HRegion中的MemStore都會Flush到HDFS中,Flush順序是MemStore大小的倒序(一個HRegion中所有MemStore總和作為該HRegion的MemStore的大小還是選取最大的MemStore作為參考?有待考證),直到總體的MemStore使用量低於hbase.regionserver.global.memstore.lowerLimit,預設38%的記憶體使用量。

3.當前HRegionServer中WAL的大小超過了hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs的數量,當前HRegionServer中所有HRegion中的MemStore都會Flush到HDFS中,Flush使用時間順序,最早的MemStore先Flush直到WAL的數量少於hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs。這裡說這兩個相乘的預設大小是2GB,查程式碼,hbase.regionserver.max.logs預設值是32,而hbase.regionserver.hlog.blocksize是HDFS的預設blocksize,32MB。但不管怎麼樣,因為這個大小超過限制引起的Flush不是一件好事,可能引起長時間的延遲,因而這篇文章給的建議:“Hint: keep hbase.regionserver.hlog.blocksize * hbase.regionserver.maxlogs just a bit above hbase.regionserver.global.memstore.lowerLimit * HBASE_HEAPSIZE.”。並且需要注意,這裡給的描述是有錯的(雖然它是官方的文件)。
在MemStore Flush過程中,還會在尾部追加一些meta資料,其中就包括Flush時最大的WAL sequence值,以告訴HBase這個StoreFile寫入的最新資料的序列,那麼在Recover時就直到從哪裡開始。在HRegion啟動時,這個sequence會被讀取,並取最大的作為下一次更新時的起始sequence。
這裡寫圖片描述

HFile格式
HBase的資料以KeyValue(Cell)的形式順序的儲存在HFile中,在MemStore的Flush過程中生成HFile,由於MemStore中儲存的Cell遵循相同的排列順序,因而Flush過程是順序寫,我們直到磁碟的順序寫效能很高,因為不需要不停的移動磁碟指標。
這裡寫圖片描述

HFile參考BigTable的SSTable和Hadoop的TFile實現,從HBase開始到現在,HFile經歷了三個版本,其中V2在0.92引入,V3在0.98引入。首先我們來看一下V1的格式:
這裡寫圖片描述

V1的HFile由多個Data Block、Meta Block、FileInfo、Data Index、Meta Index、Trailer組成,其中Data Block是HBase的最小儲存單元,在前文中提到的BlockCache就是基於Data Block的快取的。一個Data Block由一個魔數和一系列的KeyValue(Cell)組成,魔數是一個隨機的數字,用於表示這是一個Data Block型別,以快速監測這個Data Block的格式,防止資料的破壞。Data Block的大小可以在建立Column Family時設定(HColumnDescriptor.setBlockSize()),預設值是64KB,大號的Block有利於順序Scan,小號Block利於隨機查詢,因而需要權衡。Meta塊是可選的,FileInfo是固定長度的塊,它紀錄了檔案的一些Meta資訊,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等。Data Index和Meta Index紀錄了每個Data塊和Meta塊的其實點、未壓縮時大小、Key(起始RowKey?)等。Trailer紀錄了FileInfo、Data Index、Meta Index塊的起始位置,Data Index和Meta Index索引的數量等。其中FileInfo和Trailer是固定長度的。

HFile裡面的每個KeyValue對就是一個簡單的byte陣列。但是這個byte數組裡麵包含了很多項,並且有固定的結構。我們來看看裡面的具體結構:
這裡寫圖片描述

開始是兩個固定長度的數值,分別表示Key的長度和Value的長度。緊接著是Key,開始是固定長度的數值,表示RowKey的長度,緊接著是 RowKey,然後是固定長度的數值,表示Family的長度,然後是Family,接著是Qualifier,然後是兩個固定長度的數值,表示Time Stamp和Key Type(Put/Delete)。Value部分沒有這麼複雜的結構,就是純粹的二進位制資料了。隨著HFile版本遷移,KeyValue(Cell)的格式並未發生太多變化,只是在V3版本,尾部添加了一個可選的Tag陣列。

HFileV1版本的在實際使用過程中發現它佔用記憶體多,並且Bloom File和Block Index會變的很大,而引起啟動時間變長。其中每個HFile的Bloom Filter可以增長到100MB,這在查詢時會引起效能問題,因為每次查詢時需要載入並查詢Bloom Filter,100MB的Bloom Filer會引起很大的延遲;另一個,Block Index在一個HRegionServer可能會增長到總共6GB,HRegionServer在啟動時需要先載入所有這些Block Index,因而增加了啟動時間。為了解決這些問題,在0.92版本中引入HFileV2版本:
這裡寫圖片描述
在這個版本中,Block Index和Bloom Filter新增到了Data Block中間,而這種設計同時也減少了寫的記憶體使用量;另外,為了提升啟動速度,在這個版本中還引入了延遲讀的功能,即在HFile真正被使用時才對其進行解析。

FileV3版本基本和V2版本相比,並沒有太大的改變,它在KeyValue(Cell)層面上添加了Tag陣列的支援;並在FileInfo結構中添加了和Tag相關的兩個欄位。關於具體HFile格式演化介紹,可以參考這裡。

對HFileV2格式具體分析,它是一個多層的類B+樹索引,採用這種設計,可以實現查詢不需要讀取整個檔案:
這裡寫圖片描述
Data Block中的Cell都是升序排列,每個block都有它自己的Leaf-Index,每個Block的最後一個Key被放入Intermediate-Index中,Root-Index指向Intermediate-Index。在HFile的末尾還有Bloom Filter用於快速定位那麼沒有在某個Data Block中的Row;TimeRange資訊用於給那些使用時間查詢的參考。在HFile開啟時,這些索引資訊都被載入並儲存在記憶體中,以增加以後的讀取效能。

相關推薦

hbase學習教程HBase容錯性Hbase使用場景Hbase過程

HBase容錯性 Write-Ahead-Log(WAL) 該機制用於資料的容錯和恢復: 每個HRegionServer中都有一個HLog物件,HLog是一個實現Write Ahead Log的類,在每次使用者操作寫入MemStore的同時,也會寫一份

hbase學習教程HBase優化技巧HBase基本命令使用Java API對HBase伺服器進行操作

HBase優化技巧 1 修改 linux 系統引數 Linux系統最大可開啟檔案數一般預設的引數值是1024,如果你不進行修改併發量上來的時候會出現“Too Many Open Files”的錯誤,導致整個HBase不可執行,你可以用ulimit -n 命令

web全棧學習教程本系列教程介紹

系列教程 trap soft 切圖 think html4 style pes html 一、發布周期 計劃2-3天發一篇,半年左右完成。 二、教程大綱 web全棧介紹與優勢分析 本系列教程介紹 切圖與圖片介紹 html4.01 html5 css2.0 css3 頁面布

iptables實用教程管理鏈策略

否則 命令顯示 accept 目的 number cep 存在 當前 末尾 概念和原理請參考上一篇文章“iptables實用教程(一)”。 本文講解如果管理iptables中的鏈和策略。 下面的代碼格式中,下劃線表示是一個占位符,需要根據實際情況輸入參數,不帶下劃線的表示是

opencv 視覺項目學習筆記 基於 svm knn 車牌識別

its ++ eas -a rect() repr poi obj std 車牌識別的屬於常見的 模式識別 ,其基本流程為下面三個步驟: 1) 分割: 檢測並檢測圖像中感興趣區域; 2)特征提取: 對字符圖像集中的每個部分進行提取; 3)分類: 判斷圖像快是不是車牌或者 每

opencv 視覺專案學習筆記 基於 svm knn 車牌識別

車牌識別的屬於常見的 模式識別 ,其基本流程為下面三個步驟: 1) 分割: 檢測並檢測影象中感興趣區域; 2)特徵提取: 對字元影象集中的每個部分進行提取; 3)分類: 判斷影象快是不是車牌或者 每個車牌字元的分類。 車牌識別分為兩個步驟, 車牌檢測, 車牌識別, 都屬於模式識別。 基本結構如下: 一、車牌

Unity Shader入門教程 實現頂點片元著色器之間的通訊

這篇文章將介紹Pass{}內的程式碼的編寫。我們先看如下Unity Shader程式碼:(此文部分採自《unity shader入門精要》) 關於頂點著色器和片元著色器不懂的學習可以自行搜尋概念的意思,這裡就不介紹了。 Shader "Custom/myTest" {

Scala學習筆記控制結構函式

2.1 條件表示式       2.1.1 Scala中if/else語法結構和java一樣,不同點在於此if表示式有值:           val s=if (x>0) 1 else -1        //s的值要麼是1,要麼是-1,取決於X的範圍    

機器學習總結梯度消失梯度爆炸

神經網路的訓練過程通常分為兩個階段:前向傳播和反向傳播。 前向傳播如下圖所示,原理比較簡單 上一層的神經元與本層的神經元有連線,那麼本層的神經元的啟用等於上一層神經元對應的權值進行加權和運算,最後通過一個非線性函式(啟用函式)如ReLu,sigmoid等

Prometheus入門教程Prometheus + Grafana實現視覺化告警

# 文章首發於【陳樹義】公眾號,點選跳轉到原文:https://mp.weixin.qq.com/s/56S290p4j9KROB5uGRcGkQ Prometheus UI 提供了快速驗證 PromQL 以及臨時視覺化支援的能力,但其視覺化能力卻比較弱。一般情況下,我們都用 Grafana 來實現對 Pr

Python基礎List型別Tuple型別

List型別: List型別的定義: List是Python的內建型別,List是一種有序的集合。list構造簡單,直接用一對“[]”把list所用的元素括起來,並以“,”做間隔即可。list的元素並不要求必須是同類型的,一個list物件可以同時包含多個型別的元素。 L

hive學習教程hiveHbase整合

一、Hive整合HBase原理 Hive與HBase整合的實現是利用兩者本身對外的API介面互相進行通訊,相互通訊主要是依靠hive-hbase-handler-0.9.0.jar工具類,如下圖 Hive與HBase通訊示意圖 二、具體步驟

javascript學習筆記定義函數調用函數參數返回值局部全局變量

兩個 cnblogs bsp 結果 value ava ase com 調用 定義函數、調用函數、參數、返回值 關鍵字function定義函數,格式如下: function 函數名(){ 函數體 } 調用函數、參數、返回值的規則和c語言規則類似。 1 <!DOC

Nginx實用教程配置文件入門

affinity type 服務 源碼編譯 設置時間 shutdown ber 可用 控制指令 Nginx配置文件結構 nginx配置文件由指令(directive)組成,指令分為兩種形式,簡單指令和區塊指令。 一條簡單指令由指令名、參數和結尾的分號(;)組成,例如:

CSS學習筆記特性

code 背景色 左移 line tex lin 安裝 其中 cas 一、顏色特性 1. 前景色:color 用種方式指定前景色,3種方式分別是rgb顏色,#16進制編碼,顏色名稱: color: rgb(100,100,100); color: #ee3e80; col

Unity3D之Mecanim動畫系統學習筆記模型導入

leg character ... sdk ocs 物體 mat 版本 sset 我們要在Unity3D中使用上模型和動畫,需要經過下面幾個階段的制作,下面以一個人形的模型開發為準來介紹。 模型制作 模型建模(Modelling) 我們的美術在建模時一般會制作一個稱為

Git 教程時光穿梭

rac call 替換 img posit key 誤刪 ranch 定位在 我們已經成功地添加並提交了一個readme.txt文件,現在,是時候繼續工作了,於是,我們繼續修改readme.txt文件,改成如下內容: Git is a distributed version

JavaScript學習日誌面向對象的程序設計

循環 理想 soft 日誌 傳遞 數組 用例 定義 基本類型 1,ECMAScript不像其他面向對象的語言那樣有類的概念,它的對象與其他不同。 2,ECMAScript有兩種屬性:數據屬性和訪問器屬性。([[]]這種雙中括號表示屬性為內部屬性,外部不可直接訪問) 1.數據

mybatis教程概念總結

return 單個 其它 array author 擴展 地址 caf eal 一、註意規範 註意:(1).XXXmapper.xml 文件中的 namespace 等於mapper 接口地址 (2).XXXmapper.java 接口中的方法輸入參數

kubernetes學習筆記bashborad安裝配置

tag log struct recommend ide col create part describe 官方推薦方法: 連接:https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashb