Hbase基本架構原理
1. HBase框架簡單介紹
HBase是一個分散式的、面向列的開源資料庫,它不同於一般的關係資料庫,是一個適合於非結構化資料儲存的資料庫。另一個不同的是HBase基於列的而不是基於行的模式。HBase使用和 BigTable非常相同的資料模型。使用者儲存資料行在一個表裡。一個數據行擁有一個可選擇的鍵和任意數量的列,一個或多個列組成一個ColumnFamily,一個Fmaily下的列位於一個HFile中,易於快取資料。表是疏鬆的儲存的,因此使用者可以給行定義各種不同的列。在HBase中資料按主鍵排序,同時表按主鍵劃分為多個Region。
在分散式的生產環境中,HBase 需要執行在 HDFS 之上,以 HDFS 作為其基礎的儲存設施。HBase 上層提供了訪問的資料的 Java API 層,供應用訪問儲存在 HBase 的資料。在 HBase 的叢集中主要由 Master 和 Region Server 組成,以及Zookeeper,具體模組如下圖所示:
簡單介紹一下 HBase 中相關模組的作用:
- Master
HBase Master用於協調多個Region Server,偵測各個RegionServer之間的狀態,並平衡RegionServer之間的負載。HBaseMaster還有一個職責就是負責分配Region給RegionServer。HBase允許多個Master節點共存,但是這需要Zookeeper的幫助。不過當多個Master節點共存時,只有一個Master是提供服務的,其他的Master節點處於待命的狀態。當正在工作的Master節點宕機時,其他的Master則會接管HBase的叢集。
- Region Server
對於一個RegionServer而言,其包括了多個Region。RegionServer的作用只是管理表格,以及實現讀寫操作。Client直接連線RegionServer,並通訊獲取HBase中的資料。對於Region而言,則是真實存放HBase資料的地方,也就說Region是HBase可用性和分散式的基本單位。如果當一個表格很大,並由多個CF組成時,那麼表的資料將存放在多個Region之間,並且在每個Region中會關聯多個儲存的單元(Store)。
- Zookeeper
對於 HBase 而言,Zookeeper的作用是至關重要的。首先Zookeeper是作為HBase Master的HA解決方案。也就是說,是 Zookeeper保證了至少有一個HBase Master 處於執行狀態。並且Zookeeper負責Region和Region Server的註冊。其實Zookeeper發展到目前為止,已經成為了分散式大資料框架中容錯性的標準框架。不光是HBase,幾乎所有的分散式大資料相關的開源框架,都依賴於Zookeeper實現HA。
2. Hbase資料模型
2.1 邏輯檢視
基本概念:
- RowKey:是Byte array,是表中每條記錄的“主鍵”,方便快速查詢,Rowkey的設計非常重要;
- Column Family:列族,擁有一個名稱(string),包含一個或者多個相關列;
- Column:屬於某一個columnfamily,familyName:columnName,每條記錄可動態新增;
- Version Number:型別為Long,預設值是系統時間戳,可由使用者自定義;
- Value(Cell):Byte array。
2.2 物理模型:
- 每個column family儲存在HDFS上的一個單獨檔案中,空值不會被儲存。
- Key 和 Version number在每個column family中均有一份;
- HBase為每個值維護了多級索引,即:<key, columnfamily, columnname, timestamp>;
- 表在行的方向上分割為多個Region;
- Region是Hbase中分散式儲存和負載均衡的最小單元,不同Region分佈到不同RegionServer上。
- Region按大小分割的,隨著資料增多,Region不斷增大,當增大到一個閥值的時候,Region就會分成兩個新的Region;
- Region雖然是分散式儲存的最小單元,但並不是儲存的最小單元。每個Region包含著多個Store物件。每個Store包含一個MemStore或若干StoreFile,StoreFile包含一個或多個HFile。MemStore存放在記憶體中,StoreFile儲存在HDFS上。
2.3 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。
一個完整分散式的HBase的組成示意圖如下,後面我們再詳細談其工作原理。
3. 高可用
3.1 Write-Ahead-Log(WAL)保障資料高可用
我們理解下HLog的作用。HBase中的HLog機制是WAL的一種實現,而WAL(一般翻譯為預寫日誌)是事務機制中常見的一致性的實現方式。每個RegionServer中都會有一個HLog的例項,RegionServer會將更新操作(如 Put,Delete)先記錄到 WAL(也就是HLo)中,然後將其寫入到Store的MemStore,最終MemStore會將資料寫入到持久化的HFile中(MemStore 到達配置的記憶體閥值)。這樣就保證了HBase的寫的可靠性。如果沒有 WAL,當RegionServer宕掉的時候,MemStore 還沒有寫入到HFile,或者StoreFile還沒有儲存,資料就會丟失。或許有的讀者會擔心HFile本身會不會丟失,這是由 HDFS 來保證的。在HDFS中的資料預設會有3份。因此這裡並不考慮 HFile 本身的可靠性。
HFile由很多個數據塊(Block)組成,並且有一個固定的結尾塊。其中的資料塊是由一個Header和多個Key-Value的鍵值對組成。在結尾的資料塊中包含了資料相關的索引資訊,系統也是通過結尾的索引資訊找到HFile中的資料。
3.2 元件高可用
- Master容錯:Zookeeper重新選擇一個新的Master。如果無Master過程中,資料讀取仍照常進行,但是,region切分、負載均衡等無法進行;
- RegionServer容錯:定時向Zookeeper彙報心跳,如果一旦時間內未出現心跳,Master將該RegionServer上的Region重新分配到其他RegionServer上,失效伺服器上“預寫”日誌由主伺服器進行分割並派送給新的RegionServer;
- Zookeeper容錯:Zookeeper是一個可靠地服務,一般配置3或5個Zookeeper例項。
4. HBase讀寫流程
上圖是RegionServer資料儲存關係圖。上文提到,HBase使用MemStore和StoreFile儲存對錶的更新。資料在更新時首先寫入HLog和MemStore。MemStore中的資料是排序的,當MemStore累計到一定閾值時,就會建立一個新的MemStore,並且將老的MemStore新增到Flush佇列,由單獨的執行緒Flush到磁碟上,成為一個StoreFile。與此同時,系統會在Zookeeper中記錄一個CheckPoint,表示這個時刻之前的資料變更已經持久化了。當系統出現意外時,可能導致MemStore中的資料丟失,此時使用HLog來恢復CheckPoint之後的資料。
StoreFile是隻讀的,一旦建立後就不可以再修改。因此Hbase的更新其實是不斷追加的操作。當一個Store中的StoreFile達到一定閾值後,就會進行一次合併操作,將對同一個key的修改合併到一起,形成一個大的StoreFile。當StoreFile的大小達到一定閾值後,又會對 StoreFile進行切分操作,等分為兩個StoreFile。
4.1 寫操作流程
- (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的高機能。
4.2 讀操作流程
- (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