天天看點

一文講清HBase的存儲結構

![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)