
### 前言
`Hbase` 是一個分布式的、多版本、面向列的開源 `KV` 資料庫。運作在 `HDFS` 的基礎上,支援 `PB` 級别、百萬列的資料存儲。
### HBase的存儲結構
#### 邏輯存儲結構
通過下圖直覺地展示 `HBase` 的邏輯存儲結構:

在本圖中,列簇(`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` 的組成是以 `Row key` 、`CF(Column Family)` 、`Column` 和 `TimeStamp` 組成的。
`TimeStamp` 在 `HBase` 中充當的作用就是版本号,因為在 `HBase` 中有着資料多版本的特性,是以同一個 `KEY` 可以有多個版本的 `Value` 值(可以通過配置來設定多少個版本)。查詢的話是預設取回最新版本的那條資料,但是也可以進行查詢多個版本号的資料,在接下來的進階操作文章中會有示範。
##### Region Server 和 Region 的關系

- 一個 `Region Server` 就是一個機器節點(伺服器)
- 一個 `Region Server` 包含着多個 `Region`
- 一個 `Region` 包含着多個列簇 `(CF)`
- 一個 `Region Server` 中可以有多張 `Table`,一張 `Table` 可以有多個 `Region`
#### 實體存儲結構
先來看這張圖:

為了不混淆,我們可以先把以下的概念一一對應起來
邏輯結構 | 實體結構
---|---
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` 主鍵的資料,結果集如下:

更加直覺地顯示,在 `HBase` 中是以 `CF` 為單元的存儲結構。
### HBase的架構
如下圖,`HBase` 的架構圖,在 `HBase` 中我們看到有 `Client`、`Zookeeper`、`HMaster` 和 `HRegion`。

- `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 寫入資料的過程

先是 `Client` 進行發起資料的插入請求,如果 `Client` 本身存儲了關于 `Rowkey` 和 `Region` 的映射關系的話,那麼就會先查找到具體的對應關系,如果沒有的話,就會在`ZK`中進行查找到對應 `Region server`,然後再轉發到具體的 `Region` 上。所有的資料在寫入的時候先是記錄在 `WAL` 中,同時檢查關于 `MemStore` 是否滿了,如果是滿了,那麼就會進行刷盤,輸出到一個 `Hfile` 中,如果沒有滿的話,那麼就是先寫進 `Memstore` 中,然後再刷到 `WAL` 中。
#### 福利
看完後,是否對 HBase 的存儲結構有所了解了呢?最後送兩本電子書給大家,一本是《HBase權威指南(中文版)高清完整版》,一本是《HBase實戰中文版》,在公衆号背景回複 HBase 關鍵字即可擷取。
PS:畫圖的過程是真滴累啊!!!
題圖:chichimaru
