3-HBase體系結構
結構體系
部署架構
一個HBase叢集由一個Master(也可以把兩個Master做成 High Available)和多個RegionServer組成。
HBase有兩種伺服器:Master伺服器和RegionServer伺服器。
-
Master伺服器負責維護表結構資訊
-
RegionServer伺服器負責儲存實際的資料,他們直接儲存在Hadoop的HDFS上
- RegionServer非常依賴ZooKeeper服務
- ZooKeeper管理了HBase所有RegionServer的資訊,包括具體的資料段存放在哪個RegionServer上。
體系架構
HBase中的元件包括Client、Zookeeper、HMaster、HRegionServer、HRegion、Store、MemStore、StoreFile、HFile、HLog等
Client
當客戶端從ZooKeeper獲取RegionServer的地址後,它會直接從RegionServer獲取或操作(插入、刪除)資料,而不經過Master。
Client 訪問使用者資料前需要首先訪問 ZooKeeper,找到-ROOT-表的 Region 所在的位置,然後訪問-ROOT-表,接著訪問.META.表,最後才能找到使用者資料的位置去訪問。
-
.META.:記錄了使用者所有表拆分出來的的 Region 對映資訊,.META.可以有多個 Regoin
-
-ROOT-:記錄了.META.表的 Region 資訊,-ROOT-只有一個 Region,無論如何不會分裂
定址方式
三層查詢(HBase-0.96 版本以前)
- 使用者通過查詢zk(ZooKeeper) 的/hbase/root-regionserver節點來知道-ROOT-表在什麼RegionServer上
- Client 請求-ROOT-所在的 RegionServer 地址,獲取.META.表的地址,Client 會將-ROOT-的相關資訊 cache 下來,以便下一次快速訪問
- Client 請求.META.表的 RegionServer 地址,獲取訪問資料所在 RegionServer 的地址, Client 會將.META.的相關資訊 cache 下來,以便下一次快速訪問
- Client 請求訪問資料所在 RegionServer 的地址,獲取對應的資料
總結:使用者需要 3 次請求才能直到使用者 Table 真正的位置,這在一定程式帶來了效能的下降。
二層查詢(HBase-0.96 版本以後)
使用 3 層設計的主要原因是考慮到元資料可能需要很大。
每行 METADATA 資料儲存大小為 1KB 左右,如果按照一個 Region 為 128M 的計算,3 層設計可以支援的 Region 個數為 2^34 個,採用 2 層設計可以支援 2^17(131072)。使用 2 層設計的情況下,一個叢集可以儲存 4P 的資料。這僅僅是一個 Region 只有 128M 的情況下。 2 層設計就可以滿足叢集的需求,因此在 0.96 版本以後就去掉 了-ROOT-表了。
- 客戶端先通過ZooKeeper的/hbase/meta-region-server節點查詢到哪臺RegionServer上有hbase:meta表。
- 客戶端連線含有hbase:meta表的RegionServer。 hbase:meta表儲存了所有Region的行鍵範圍資訊, 通過這個表就可以查詢出你要存取的rowkey屬於哪個Region的範圍裡面, 以及這個Region又是屬於哪個RegionServer。
- 獲取這些資訊後, 客戶端就可以直連其中一臺擁有你要存取的rowkey的RegionServer, 並直接對其操作。
- 客戶端會把meta資訊快取起來,下次操作就不需要進行以上載入hbase:meta的步驟了。
Zookeeper
元資料表hbase:meata的位置儲存在ZooKeeper
HDFS
真正承載資料的載體
Master
Master只負責各種協調工作,如建表、刪表、移動Region、合併等操作。
RegionServer
RegionServer就是存放Region的容器,直觀上說就是伺服器上的一個服務。RegionServer上有一個或者多個Region,資料就儲存在Region上。
RegionServer的內部架構圖
-
WAL(Write-Ahead Log):預寫日誌。當操作到達Region的時候,HBase先把操作寫到WAL裡面。 HBase會先把資料放到基於記憶體實現的Memstore裡,等資料達到一定的數量時才刷寫(flush)到最終儲存的HFile內。
-
多個Region:Region相當於一個數據分片,每一個Region都有起始rowkey和結束rowkey,代表了它所儲存的row範圍。
Region
Region就是一段資料的集合。HBase中的表一般擁有一個到多個Region。
Region有以下特性:
- Region不能跨伺服器,一個RegionServer上有一個或者多個Region。
- 資料量小的時候,一個Region足以儲存所有資料;但是,當資料量大的時候,HBase會拆分Region。
- 當HBase在進行負載均衡的時候,也有可能會從一臺RegionServer上把Region移動到另一臺RegionServer上。
- Region是基於HDFS的,它的所有資料存取操作都是呼叫了HDFS的客戶端介面來實現的。
一個Region就是多個行的集合。在Region中行的排序按照行鍵(rowkey)字典排序。
Region 內部結構圖
一個Region包含有:
- 多個Store:每一個Region內都包含有多個Store例項。一個Store對應一個列族的資料,如果一個表有兩個列族,那麼在一個Region裡面就有兩個Store。在最右邊的單個Store的解剖圖上,我們可以看到Store內部有MemStore和HFile這兩個組成部分。
Store
Store中有兩個重要組成部分:
-
MemStore:每個Store中有一個MemStore例項。 資料寫入WAL之後就會被放入MemStore。 MemStore是記憶體的儲存物件, 只有當MemStore滿了的時候才會將資料刷寫(flush) 到HFile中
-
HFile:在Store中有多個HFile。 當MemStore滿了之後HBase就會在HDFS上生成一個新的HFile, 然後把MemStore中的內容寫到這個HFile中。HFile直接跟HDFS打交道,它是資料的儲存實體。
Store內部結構圖
MemStore
Memstore是儲存在記憶體中,Memstore存在的意義是維持資料按照rowkey順序排列,而不是做一個快取
使用記憶體先把資料整理成順序存放,然後再一起寫入硬碟。
資料被寫入WAL之後就會被載入到MemStore中去。 MemStore的大小增加到超過一定閥值的時候就會被刷寫到HDFS上, 以HFile的形式被持久化起來。
HFile(StoreFile)
HFile是資料儲存的實際載體,我們建立的所有表、列等資料都儲存在HFile裡面。HFile是由一個一個的塊組成的。 在HBase中一個塊的大小預設為64KB, 由列族上的BLOCKSIZE屬性定義。
MemStore刷寫而成的檔案叫HFile, StoreFile就是HFile的抽象類
HFile的組成
- Data (資料塊) :每個HFile有多個Data塊。儲存HBase表中的資料。可選的
- Meta(元資料塊):Meta塊是可選的,Meta塊只有在檔案關閉的時候才會寫入。Meta塊儲存了該HFile檔案的元資料資訊
- FileInfo(檔案資訊):只有在檔案關閉的時候寫入。儲存的是這個檔案的資訊,比如最後一個Key(Last
Key) ,平均的Key長度(Avg Key Len)等。必選的 - DataIndex(儲存Data塊索引資訊的塊檔案):索引的資訊也就是Data塊的偏移值(offset)。可選的
- MetaIndex(儲存Meta塊索引資訊的塊檔案):可選的
- Trailer:儲存了FileInfo、 DataIndex、 MetaIndex塊的偏移值。必選的
Data資料塊
Data資料塊的第一位儲存的是塊的型別, 後面儲存的是多個KeyValue鍵值對, 也就是單元格(Cell)的實現類。 Cell是一個介面,KeyValue是它的實現類。
- BlockType(塊型別)
- DATA
- ENCODED_DATA
- LEAF_INDEX
- BLOOM_CHUNK
- META
- INTERMEDIATE_INDEX
- ROOT_INDEX
- FILE_INFO
- GENERAL_BLOOM_META
- DELETE_FAMILY_BLOOM_META
- TRAILER
- INDEX_V1
KeyValue類
一個KeyValue類裡面最後一個部分是儲存資料的Value,而前面的部分都是儲存跟該單元格相關的元資料資訊。如果你儲存的value很小,那麼這個單元格的絕大部分空間就都是rowkey、columnfamily、column等的元資料,所以大家的列族和列的名字如果很長,大部分的空間就都被拿來儲存這些資料了。
採用適當的壓縮演算法就可以極大地節省儲存列族、 列等資訊的空間。壓縮和解壓必然帶來效能損耗
KeyValue類結構圖
資料儲存順序
WAL是儲存在HDFS上的, Memstore是儲存在記憶體中的, HFile也是儲存在HDFS上的。
資料是先寫入WAL, 再被放入Memstore, 最後被持久化到HFile中。
預寫日誌(Log)
預寫日誌(Write-ahead log,WAL) 就是設計來解決宕機之後的操作恢復問題的。資料到達Region的時候是先寫入WAL,然後再被載入到Memstore的。WAL的資料是儲存在HDFS。
關閉或開啟WAL特性
WAL是預設開啟的
Mutation.setDurability(Durability.SKIP_WAL)
-- 方法來設定和獲取欄位的值
Mutation.getDurability()
- 在HBase的Java API中,指定寫入時不使用WAL log
Put put = new Put(rowKey);
put.setWriteToWAL(false);
- 在HBase shell中,關閉一張表的WAL log
disable 'TABLE_NAME'
alter 'TABLE_NAME', DURABILITY => 'SKIP_WAL'
enable 'TABLE_NAME'
延遲(非同步)同步寫入WAL
Mutation.setDurability(Durability.ASYNC_WAL)
DURABILITY可選的值有ASYNC_WAL, FSYNC_WAL, SKIP_WAL, SYNC_WAL(預設值), USE_DEFAULT等
- ASYNC_WAL
Write the Mutation to the WAL asynchronously - FSYNC_WAL
Write the Mutation to the WAL synchronously and force the entries to disk. - SKIP_WAL
Do not write the Mutation to the WAL - SYNC_WAL
Write the Mutation to the WAL synchronously. - USE_DEFAULT
If this is for tables durability, use HBase's global default value (SYNC_WAL).
WAL 滾動
WAL的檢查間隔由hbase.regionserver.logroll.period定義, 預設值為1小時。檢查的內容是把當前WAL中的操作跟實際持久化到HDFS上的操作比較,看哪些操作已經被持久化了,被持久化的操作就會被移動到.oldlogs資料夾內
一個WAL例項包含有多個WAL檔案。 WAL檔案的最大數量通過hbase.regionserver.maxlogs(預設是32) 引數來定義
觸發滾動條件
- 當WAL檔案所在的塊(Block) 快要滿了
- 當WAL所佔的空間大於或者等於某個閥值,該閥值的計算公式:
hbase.regionserver.hlog.blocksize * hbase.regionserver.logroll.multiplier
- hbase.regionserver.hlog.blocksize: 儲存系統的塊大小,若基於HDFS,則設定為HDFS的塊大小
- hbase.regionserver.logroll.multiplier:預設值0.95。即當WAL檔案所佔的空間大於或者等於95%的塊大小, 則這個WAL檔案就會被歸檔到.oldlogs資料夾內
WAL歸檔
WAL檔案被創建出來後會放在/hbase/.log,一旦WAL檔案被判定為要歸檔,則會被移動到/hbase/.oldlogs資料夾。
當這個WAL不需要作為用來恢復資料的備份時,Master會負責定期地去清理.oldlogs資料夾。
引用WAL檔案的場景:
- TTL程序: 該程序會保證WAL檔案一直存活直到達到hbase.master.logcleaner.ttl定義的超時時間(預設10分鐘) 為止
- 備份(replication) 機制: 如果你開啟了HBase的備份機制,那麼HBase要保證備份叢集已經完全不需要這個WAL檔案了,才會刪除這個WAL檔案。
只有當該WAL檔案沒有被以上兩種情況引用時, 才會被系統徹底地刪除掉。
資料儲存架構
結構圖
表結構圖
行結構
Namespace(表名稱空間)
表名稱空間的作用是把多個屬於相同業務領域的表分成一個組。
在建表時可以新增上名稱空間( HBase中預定義2個保留表空間 一個表由一個或者多個列族組成 一個行包含了多個列,這些列通過列族來分類。一行中的資料可以分佈在不同的伺服器上。 rowkey行鍵可以是任意字串(最大長度是 64KB,實際應用中長度一般為 10-100bytes),最好是16。在 HBase 內部,rowkey 儲存為位元組陣列。每個行(row)都擁有唯一的行鍵(row key)來確定其唯一性。rowkey就是決定row儲存順序和位置的唯一憑證。 HBase中無法根據某個column來排序,只能根據rowkey來排序(字典順序) 最基本的儲存單位是列(column),一個列或者多個列形成一行(row)。 在HBase中,行跟行的列可以完全不一樣,這個行的資料跟另外一個行的資料也可以儲存在不同的機器上,甚至同一行內的列也可以儲存在完全不同的機器上。 1、基於Rowkey的單行查詢 2、基於Rowkey的範圍掃描 3、全表掃描 若干列可以組成列族(Column Family)。Hbase通過列族劃分資料的儲存,列族下面可以包含任意多的列,實現靈活的資料存取。 Hbase表的建立的時候就必須指定列族,不需要指定列。 Hbase的列族不是越多越好,官方推薦的是列族最好小於或者等於3。我們使用的場景一般是1個列族。 表屬性(如:過期時間,資料塊快取,是否壓縮等屬性)都是定義在列簇上。 在HBase中一個列的名稱前面總是帶著他所屬的列族,它的格式是( 列族:列名 )。 在Hbase中使用不同的timestame來標識相同rowkey行對應的不同版本的資料。用來標定同一個列中多個單元格的版本號。 版本通過時間戳來索引。時間戳的型別是 64 位整型。時間戳可以由hbase(在資料寫入時自動)賦值,它是精確到毫秒的當前系統時間。時間戳也可以由使用者顯式賦值。每個 cell 中,不同版本的資料按照時間倒序排序,即最新的資料排在最前面。 hbase 提供了兩種資料版本回收方式 一個列上可以儲存多個版本的值,每個版本就稱為單元格(Cell)。多個版本的值被儲存到多個單元格中,多個版本之間用timestame(Version)來區分。因此,由行鍵:列族:列:版本號(rowkey:column family:column:version)來唯一確定一條結果。)
保留表空間
Table(表)
Row(行)
Row key
column
Hbase只支援3中查詢方式
Column Family
TimeStamp(時間戳/版本號)
多版本資料管理
Cell(單元格)