一文講清HBase的儲存結構

spacedong發表於2019-01-21

![image](http://image.spacedong.top/Swan%20River.jpg)
### 前言
`Hbase` 是一個分散式的、多版本、面向列的開源 `KV` 資料庫。執行在 `HDFS` 的基礎上,支援 `PB` 級別、百萬列的資料儲存。

### HBase的儲存結構
#### 邏輯儲存結構
通過下圖直觀地展示 `HBase` 的邏輯儲存結構:

![HBase 邏輯檢視](http://image.spacedong.top/Hbase%20%E9%80%BB%E8%BE%91%E8%A7%86%E5%9B%BEjpg%20%281%29.jpg)

在本圖中,列簇(`Column Family`)對應的值就是 `info` 和 `area` ,列( `Column` 或者稱為 `Qualifier` )對應的就是 `name` 、 `age` 、 `country` 和 `city` ,`Row key` 對應的就是 `Row 1` 和 `Row 2`,`Cell` 對應的就是具體的值。

– `Row key` :表的主鍵,按照字典序排序。
– 列簇:在 `HBase` 中,列簇將表進行橫向切割。
– 列:屬於某一個列簇,在 `HBase` 中可以進行動態的新增。
– `Cell` : 是指具體的 `Value` 。
– `Version` :在這張圖裡面沒有顯示出來,這個是指版本號,用時間戳(`TimeStamp` )來表示。

看完這張圖,是不是有點疑惑,怎麼獲取其中的一條資料呢?既然 `HBase` 是 `KV` 的資料庫,那麼當然是以獲取 `KEY` 的形式來獲取到 `Value` 啦。在 `HBase` 中的 `KEY` 組成是這樣的:

![Key 和 Value 圖](http://image.spacedong.top/Hbase%20Key%E7%BB%84%E6%88%90.jpg)

`KEY` 的組成是以 `Row key` 、`CF(Column Family)` 、`Column` 和 `TimeStamp` 組成的。

`TimeStamp` 在 `HBase` 中充當的作用就是版本號,因為在 `HBase` 中有著資料多版本的特性,所以同一個 `KEY` 可以有多個版本的 `Value` 值(可以通過配置來設定多少個版本)。查詢的話是預設取回最新版本的那條資料,但是也可以進行查詢多個版本號的資料,在接下來的進階操作文章中會有演示。

##### Region Server 和 Region 的關係

![Region Server 和 Region 關係圖](http://image.spacedong.top/Region%20Server%20%E5%92%8C%20Region%20%E7%9A%84%E5%85%B3%E7%B3%BB.jpg)
– 一個 `Region Server` 就是一個機器節點(伺服器)
– 一個 `Region Server` 包含著多個 `Region`
– 一個 `Region` 包含著多個列簇 `(CF)`
– 一個 `Region Server` 中可以有多張 `Table`,一張 `Table` 可以有多個 `Region`

#### 物理儲存結構
先來看這張圖:

![Hbase架構圖](http://image.spacedong.top/Hbase%E7%89%A9%E7%90%86%E5%AD%98%E5%82%A8%E6%9E%B6%E6%9E%84.png)

為了不混淆,我們可以先把以下的概念一一對應起來

邏輯結構 | 物理結構
—|—
Region Server | HRegion Server
Region | HRegion
CF | HStore(這裡指的是Store)

在具體的物理結構中
– `HRegion Server` 就是一個機器節點,包含多個 `HRegion` ,但是這些 `HRegion` 不一定是來自於同一個 `Table` ,負責響應的是使用者的 `IO` 請求,和 `HDFS` 進行互動,是伺服器中的一個程式。
– `HRegion` 包含多個 `HStore` 。
– 一個 `CF` 組成一個 `HStore` ,預設是 `10 G`,如果大於 `10G` 會進行分裂。`HStore` 是 `HBase` 的核心儲存單元,一個 `HStore` 由 `MemStore` 和 `StoreFile` 組成。
– `MemStore` 是一塊記憶體,預設大小是 `128M`,如果超過了這個大小,那麼就會進行刷盤,把記憶體裡的資料刷進到 `StoreFile` 中。
– 在 `HStore` 對應著的是 `Table` 裡面的 `Column Family`,不管有 `CF` 中有多少的資料,都會儲存在 `HStore` 中,為了避免訪問不同的 `HStore` 而導致的效率低下。
– `HRegion` 是 `Hbase` 中分散式儲存和負載均衡的最小單元,但不是儲存的最小單元。
– 一個 `Hstore` 可以有多個 `StoreFile`

#### 在HBase中查詢不同的CF的資料
從不同的 `CF` 中查詢 `Row 3` 主鍵的資料,結果集如下:

![查詢Row 3的資料](http://image.spacedong.top/%E9%80%BB%E8%BE%91%E5%92%8C%E7%89%A9%E7%90%86%E6%98%A0%E5%B0%84.png)

更加直觀地顯示,在 `HBase` 中是以 `CF` 為單元的儲存結構。

### HBase的架構
如下圖,`HBase` 的架構圖,在 `HBase` 中我們看到有 `Client`、`Zookeeper`、`HMaster` 和 `HRegion`。

![HBase的架構圖](http://image.spacedong.top/Hbase%E6%9E%B6%E6%9E%84%E5%9B%BEpng.png)

– `Client` 是客戶端,要求讀寫資料的發起者。
– `ZK` 叢集是負責轉發 `Client` 的請求和提供心跳機制,會讓 `HRegion Server` 和 `HRegion` 註冊進來,同時儲存著 `Rowkey` 和 `Region` 的對映關係。
– `HMaster` 中可以有多個待命,只有一個在活躍。

#### Hbase讀取資料的過程
`Client` 請求讀取資料時,先轉發到 `ZK` 叢集,在 `ZK` 叢集中尋找到相對應的 `Region Server`,再找到對應的 `Region`,先是查 `MemStore`,如果在 `MemStore` 中獲取到資料,那麼就會直接返回,否則就是再由 `Region` 找到對應的 `Store File`,從而查到具體的資料。

在整個架構中,`HMaster` 和 `HRegion Server` 可以是同一個節點上,可以有多個 `HMaster` 存在,但是隻有一個 `HMaster` 在活躍。

在 `Client` 端會進行 `rowkey`-> `HRegion` 對映關係的快取,降低下次定址的壓力。

#### HBase 寫入資料的過程

![在HBase中寫入資料的過程](http://image.spacedong.top/Hbase%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE.png)

先是 `Client` 進行發起資料的插入請求,如果 `Client` 本身儲存了關於 `Rowkey` 和 `Region` 的對映關係的話,那麼就會先查詢到具體的對應關係,如果沒有的話,就會在`ZK`中進行查詢到對應 `Region server`,然後再轉發到具體的 `Region` 上。所有的資料在寫入的時候先是記錄在 `WAL` 中,同時檢查關於 `MemStore` 是否滿了,如果是滿了,那麼就會進行刷盤,輸出到一個 `Hfile` 中,如果沒有滿的話,那麼就是先寫進 `Memstore` 中,然後再刷到 `WAL` 中。

#### 福利

看完後,是否對 HBase 的儲存結構有所瞭解了呢?最後送兩本電子書給大家,一本是《HBase權威指南(中文版)高清完整版》,一本是《HBase實戰中文版》,在公眾號後臺回覆 HBase 關鍵字即可獲取。

PS:畫圖的過程是真滴累啊!!!

題圖:chichimaru

![image](http://image.spacedong.top/wechatqcode.jpg)


相關文章