深刻理解 Hbase 架構(翻譯)

最近在網上看到一篇很好的講 HBase 架構的文章(原文在這裏),簡潔明瞭,圖文並茂,因此這裏將其翻譯成中文分享。圖片引用的是原文中的,技術性術語會盡可能使用英文,在比較重要的段落後面都會加上我我的理解的點評。node

HBase 架構組件

物理上,Hbase 是由三種類型的 server 組成的的主從式(master-slave)架構:算法

  • Region Server 負責處理數據的讀寫請求,客戶端請求數據時直接和 Region Server 交互。
  • HBase Master 負責 Region 的分配,DDL(建立,刪除 table)等操做。
  • Zookeeper,做爲 HDFS 的一部分,負責維護集羣狀態。

固然底層的存儲都是基於 Hadoop HDFS 的:數據庫

  • Hadoop DataNode 負責存儲 Region Server 所管理的數據。全部的 HBase 數據都存儲在 HDFS 文件中。Region Server 和 HDFS DataNode 每每是分佈在一塊兒的,這樣 Region Server 就可以實現數據本地化(data locality,即將數據放在離須要者儘量近的地方)。HBase 的數據在寫的時候是本地的,可是當 region 被遷移的時候,數據就可能再也不知足本地性了,直到完成 compaction,才能又恢復到本地。
  • Hadoop NameNode 維護了全部 HDFS 物理 data block 的元信息。

圖片描述

Regions

HBase Table)根據 rowkey 的範圍被水平拆分成若干個 region。每一個 region 都包含了這個region 的 start keyend key 之間的全部row)。Regions 被分配給集羣中的某些節點來管理,即 Region Server,由它們來負責處理數據的讀寫請求。每一個 Region Server 大約能夠管理 1000 個 regions。緩存

圖片描述

HBase Master

也叫 HMaster,負責 Region 的分配,DDL(建立,刪除表)等操做:安全

統籌協調全部 region server:服務器

  • 啓動時分配 regions,在故障恢復和負載均衡時重分配 regions
  • 監控集羣中全部 Region Server 實例(從 Zookeeper 獲取通知信息)

管理員功能:網絡

  • 提供建立,刪除和更新 HBase Table 的接口

圖片描述

Zookeeper

HBase 使用 Zookeeper 作分佈式管理服務,來維護集羣中全部服務的狀態。Zookeeper 維護了哪些 servers 是健康可用的,而且在 server 故障時作出通知。Zookeeper 使用一致性協議來保證分佈式狀態的一致性。注意這須要三臺或者五臺機器來作一致性協議。session

圖片描述

這些組件是如何一塊兒工做的

Zookeeper 用來協調分佈式系統中集羣狀態信息的共享。Region Servers 和 在線 HMaster(active HMaster)和 Zookeeper 保持會話(session)。Zookeeper 經過心跳檢測來維護全部臨時節點(ephemeral nodes)。架構

圖片描述

每一個 Region Server 都會建立一個 ephemeral 節點。HMaster 會監控這些節點來發現可用的 Region Servers,一樣它也會監控這些節點是否出現故障。app

HMaster 們會競爭建立 ephemeral 節點,而 Zookeeper 決定誰是第一個做爲在線 HMaster,保證線上只有一個 HMaster。在線 HMaster(active HMaster) 會給 Zookeeper 發送心跳,不在線的待機 HMaster (inactive HMaster) 會監聽 active HMaster 可能出現的故障並隨時準備上位。

若是有一個 Region Server 或者 HMaster 出現故障或各類緣由致使發送心跳失敗,它們與 Zookeeper 的 session 就會過時,這個 ephemeral 節點就會被刪除下線,監聽者們就會收到這個消息。Active HMaster 監聽的是 region servers 下線的消息,而後會恢復故障的 region server 以及它所負責的 region 數據。而 Inactive HMaster 關心的則是 active HMaster 下線的消息,而後競爭上線變成 active HMaster。

(點評:這一段很是重要,涉及到分佈式系統設計中的一些核心概念,包括集羣狀態、一致性等。能夠看到 Zookeeper 是溝通一切的橋樑,全部的參與者都和 Zookeeper 保持心跳會話,並從 Zookeeper 獲取它們須要的集羣狀態信息,來管理其它節點,轉換角色,這也是分佈式系統設計中很重要的思想,由專門的服務來維護分佈式集羣狀態信息。)

第一次讀和寫操做

有一個特殊的 HBase Catalog 表叫 Meta table(它實際上是一張特殊的 HBase 表),包含了集羣中全部 regions 的位置信息。Zookeeper 保存了這個 Meta table 的位置。

當 HBase 第一次讀或者寫操做到來時:

  • 客戶端從 Zookeeper 那裏獲取是哪一臺 Region Server 負責管理 Meta table。
  • 客戶端會查詢那臺管理 Meta table 的 Region Server,進而獲知是哪一臺 Region Server 負責管理本次數據請求所須要的 rowkey。客戶端會緩存這個信息,以及 Meta table 的位置信息自己。
  • 而後客戶端回去訪問那臺 Region Server,獲取數據。

對於之後的的讀請求,客戶端從能夠緩存中直接獲取 Meta table 的位置信息(在哪一臺 Region Server 上),以及以前訪問過的 rowkey 的位置信息(哪一臺 Region Server 上),除非由於 Region 被遷移了致使緩存失效。這時客戶端會重複上面的步驟,從新獲取相關位置信息並更新緩存。

圖片描述

(點評:客戶端讀寫數據,實際上分了兩步:第一步是定位,從 Meta table 獲取 rowkey 屬於哪一個 Region Server 管理;第二步再去相應的 Region Server 讀寫數據。這裏涉及到了兩個 Region Server,要理解它們各自的角色功能。關於 Meta table 下面會詳細介紹。)

HBase Meta Table

Meta table 是一個特殊的 HBase table,它保存了系統中全部的 region 列表。這張 table 相似一個 b-tree,結構大體以下:

  • Key:table, region start key, region id
  • Value:region server

圖片描述

Region Server 組成

Region Server 運行在 HDFS DataNode 上,由如下組件組成:

  • WAL:Write Ahead Log 是分佈式文件系統上的一個文件,用於存儲新的還未被持久化存儲的數據,它被用來作故障恢復。
  • BlockCache:這是讀緩存,在內存中存儲了最常訪問的數據,是 LRU(Least Recently Used)緩存。
  • MemStore:這是寫緩存,在內存中存儲了新的還未被持久化到硬盤的數據。當被寫入硬盤時,數據會首先被排序。注意每一個 Region 的每一個 Column Family 都會有一個 MemStore。
  • HFile 在硬盤上(HDFS)存儲 HBase 數據,以有序 KeyValue 的形式。

圖片描述

(點評:這一段是重中之重,理解 Region Server 的組成對理解 HBase 的架構相當重要,要充分認識 Region Server 的功能,以及每一個組件的做用,這些組件的行爲和功能在後續的段落中都會一一展開。)

HBase 寫數據步驟

當客戶端發起一個寫數據請求(Put 操做),第一步首先是將數據寫入到 WAL 中:

  • 新數據會被追加到 WAL 文件尾部。
  • WAL 用來在故障恢復時恢復還未被持久化的數據。

圖片描述

數據被寫入 WAL 後,會被加入到 MemStore 即寫緩存。而後服務端就能夠向客戶端返回 ack 表示寫數據完成。

(點評:注意數據寫入時 WAL 和 MemStore 更新的順序,不能調換,必須先 WAL 再 MemStore。若是反過來,先更新完 MemStore,此時 Region Server 發生 crash,內存中的更新就丟失了,而此時數據還未被持久化到 WAL,就沒法恢復了。理論上 WAL 就是 MemStore 中數據的一個鏡像,應該保持一致,除非發生系統 crash。另外注意更新 WAL 是在文件尾部追加的方式,這種磁盤操做性能很高,不會太影響請求的總體響應時間。)

圖片描述

HBase MemStore

MemStore 在內存中緩存 HBase 的數據更新,以有序 KeyValues 的形式,這和 HFile 中的存儲形式同樣。每一個 Column Family 都有一個 MemStore,全部的更新都以 Column Family 爲單位進行排序。

圖片描述

HBase Region Flush

MemStore 中累積了足夠多的的數據後,整個有序數據集就會被寫入一個新的 HFile 文件到 HDFS 上。HBase 爲每一個 Column Family 都建立一個 HFile,裏面存儲了具體的 Cell,也即 KeyValue 數據。隨着時間推移,HFile 會不斷產生,由於 KeyValue 會不斷地從 MemStore 中被刷寫到硬盤上。

注意這也是爲何 HBase 要限制 Column Family 數量的一個緣由。每一個 Column Family 都有一個 MemStore;若是一個 MemStore 滿了,全部的 MemStore 都會被刷寫到硬盤。同時它也會記錄最後寫入的數據的最大序列號sequence number),這樣系統就能知道目前爲止哪些數據已經被持久化了。

最大序列號是一個 meta 信息,被存儲在每一個 HFile 中,來表示持久化進行到哪條數據了,應該從哪裏繼續。當 region 啓動時,這些序列號會被讀取,取其中最大的一個,做爲基礎序列號,後面的新的數據更新就會在該值的基礎上遞增產生新的序列號。

圖片描述

(點評:這裏有個序列號的概念,每次 HBase 數據更新都會綁定一個新的自增序列號。而每一個 HFile 則會存儲它所保存的數據的最大序列號,這個元信息很是重要,它至關於一個 commit point,告訴咱們在這個序列號以前的數據已經被持久化到硬盤了。它不只在 region 啓動時會被用到,在故障恢復時,也能告訴咱們應該從 WAL 的什麼位置開始回放數據的歷史更新記錄。)

HBase HFile

數據存儲在 HFile 中,以 Key/Value 形式。當 MemStore 累積了足夠多的數據後,整個有序數據集就會被寫入一個新的 HFile 文件到 HDFS 上。整個過程是一個順序寫的操做,速度很是快,由於它不須要移動磁盤頭。(注意 HDFS 不支持隨機修改文件操做,但支持 append 操做。)

圖片描述

HBase HFile 文件結構

HFile 使用多層索引來查詢數據而沒必要讀取整個文件,這種多層索引相似於一個 B+ tree:

  • KeyValues 有序存儲。
  • rowkey 指向 index,而 index 則指向了具體的 data block,以 64 KB 爲單位。
  • 每一個 block 都有它的葉索引。
  • 每一個 block 的最後一個 key 都被存儲在中間層索引。
  • 索引根節點指向中間層索引。

trailer 指向原信息數據塊,它是在數據持久化爲 HFile 時被寫在 HFile 文件尾部。trailer 還包含例如布隆過濾器和時間範圍等信息。布隆過濾器用來跳過那些不包含指定 rowkey 的文件,時間範圍信息則是根據時間來過濾,跳過那些不在請求的時間範圍以內的文件。

圖片描述

HFile 索引

剛纔討論的索引,在 HFile 被打開時會被載入內存,這樣數據查詢只要一次硬盤查詢。

圖片描述

HBase Read 合併

咱們已經發現,每行(row)的 KeyValue cells 可能位於不一樣的地方,這些 cell 可能被寫入了 HFile,多是最近剛更新的,還在 MemStore 中,也可能最近剛讀過,緩存在 Block Cache 中。因此,當你讀一行 row 時,系統怎麼將對應的 cells 返回呢?一次 read 操做會將 Block Cache,MemStore 和 HFile 中的 cell 進行合併:

  • 首先 scanner 從 Block Cache 讀取 cells。最近讀取的 KeyValue 都被緩存在這裏,這是 一個 LRU 緩存。
  • 而後 scanner 讀取 MemStore,即寫緩存,包含了最近更新的數據。
  • 若是 scanner 沒有在 BlockCache 和 MemStore 都沒找到對應的 cells,則 HBase 會使用 Block Cache 中的索引和布隆過濾器來加載對應的 HFile 到內存,查找到請求的 row cells。

圖片描述

以前討論過,每一個 MemStore 可能會有多個 HFile,因此一次 read 請求可能須要多讀個文件,這可能會影響性能,這被稱爲讀放大read amplification)。

(點評:從時間軸上看,一個個的 HFile 也是有序的,本質上它們保存了每一個 region 的每一個 column family 的數據歷史更新。因此對於同一個 rowkey 的同一個 cell,它可能也有多個版本的數據分佈在不一樣的 HFile 中,因此可能須要讀取多個 HFiles,這樣性能開銷會比較大,尤爲是當不知足 data locality 時這種 read amplification 狀況會更加嚴重。這也是後面會講到的 compaction 必要的緣由)

圖片描述

HBase Minor Compaction

HBase 會自動合併一些小的 HFile,重寫成少許更大的 HFiles。這個過程被稱爲 minor compaction。它使用歸併排序算法,將小文件合併成大文件,有效減小 HFile 的數量。

圖片描述

HBase Major Compaction

Major Compaction 合併重寫每一個 Column Family 下的全部的 HFiles,成爲一個單獨的大 HFile,在這個過程當中,被刪除的和過時的 cell 會被真正從物理上刪除,這能提升讀的性能。可是由於 major compaction 會重寫全部的 HFile,會產生大量的硬盤 I/O 和網絡開銷。這被稱爲寫放大Write Amplification)。

Major compaction 能夠被設定爲自動調度。由於存在 write amplification 的問題,major compaction 通常都安排在週末和半夜。MapR 數據庫對此作出了改進,並不須要作 compaction。Major compaction 還能將由於服務器 crash 或者負載均衡致使的數據遷移從新移回到離 Region Server 的地方,這樣就能恢復 data locality

圖片描述

Region = Contiguous Keys

咱們再來回顧一下 region 的概念:

  • HBase Table 被水平切分紅一個或數個 regions。每一個 region 包含了連續的,有序的一段 rows,以 start key 和 end key 爲邊界。
  • 每一個 region 的默認大小爲 1GB。
  • region 裏的數據由 Region Server 負責讀寫,和 client 交互。
  • 每一個 Region Server 能夠管理約 1000 個 regions(它們可能來自一張表或者多張表)。

圖片描述

Region 分裂

一開始每一個 table 默認只有一個 region。當一個 region 逐漸變得很大時,它會分裂(split)成兩個子 region,每一個子 region 都包含了原來 region 一半的數據,這兩個子 region 並行地在原來這個 region server 上建立,這個分裂動做會被報告給 HMaster。處於負載均衡的目的,HMaster 可能會將新的 region 遷移給其它 region server。

圖片描述

Read 負載均衡

Splitting 一開始是發生在同一臺 region server 上的,可是出於負載均衡的緣由,HMaster 可能會將新的 regions 遷移給它 region server,這會致使那些 region server 須要訪問離它比較遠的 HDFS 數據,直到 major compaction 的到來,它會將那些遠方的數據從新移回到離 region server 節點附近的地方。

(點評:注意這裏的遷移的概念,只是邏輯上的遷移,即將某個 region 交給另外一個 region server 管理。)

圖片描述

HDFS 數據備份

全部的讀寫都發生在 HDFS 的主 DataNode 節點上。 HDFS 會自動備份 WAL 和 HFile 的文件 blocks。HBase 依賴於 HDFS 來保證數據完整安全。當數據被寫入 HDFS 時,一份會寫入本地節點,另外兩個備份會被寫入其它節點。

圖片描述

WAL 和 HFiles 都會持久化到硬盤並備份。那麼 HBase 是怎麼恢復 MemStore 中還未被持久化到 HFile 的數據呢?下面的章節會討論這個問題。

圖片描述

HBase 故障恢復

當某個 Region Server 發生 crash 時,它所管理的 region 就沒法被訪問了,直到 crash 被檢測到,而後故障恢復完成,這些 region 才能恢復訪問。Zookeeper 依靠心跳檢測發現節點故障,而後 HMaster 會收到 region server 故障的通知。

當 HMaster 發現某個 region server 故障,HMaster 會將這個 region server 所管理的 regions 分配給其它健康的 region servers。爲了恢復故障的 region server 的 MemStore 中還未被持久化到 HFile 的數據,HMaster 會將 WAL 分割成幾個文件,將它們保存在新的 region server 上。每一個 region server 而後回放各自拿到的 WAL 碎片中的數據,來爲它所分配到的新 region 創建 MemStore。

圖片描述

WAL 包含了一系列的修改操做,每一個修改都表示一個 put 或者 delete 操做。這些修改按照時間順序依次寫入,持久化時它們被依次寫入 WAL 文件的尾部。

當數據仍然在 MemStore 還未被持久化到 HFile 怎麼辦呢?WAL 文件會被回放。操做的方法是讀取 WAL 文件,排序並添加全部的修改記錄到 MemStore,最後 MemStore 會被刷寫到 HFile。

圖片描述

(點評:故障恢復是 HBase 可靠性保障的一個重要特性。WAL 在這裏扮演了關鍵角色,在分割 WAL 時,數據會根據 region 分配到對應的新的 region server 上,而後 region server 負責回放這一部分數據到 MemStore 中。)

Apache HBase 架構的優勢

  • 強一致性:

    - 當 write 返回時,全部的 reader 都會讀到一樣的值。
  • 自動擴展性

    - 數據變大時 region 會分裂。
    - 使用 HDFS 存儲備份數據。
  • 內置恢復功能

    - 使用 Write Ahead Log (相似於文件系統中的日誌)
  • 與 Hadoop 結合:

    - 使用 MapReduce 處理 HBase 數據會很是直觀。

Apache HBase 也有問題

  • 業務持續可靠性:

    - WAL 回放很慢。
    - 故障恢復很慢。
    - Major Compaction 時候 I/O 會飆升。
相關文章
相關標籤/搜索