HBase 資料庫學習筆記
HBase 作為 Google BigTable 的開源實現,廣泛應用於互聯網行業中。本文作為個人的學習筆記,主要從數據模型、集群架構和單機存儲引擎的實現以及與另一個開源列族資料庫 Cassandra 的對比四個維度進行學習記錄。
HBase 的數據模型
邏輯上來說,和傳統關係型資料庫類似,HBase也是以表的方式組織數據,每一張表也有數據行和列,但是在 HBase 資料庫中的行和列又和關係型資料庫稍有不同。下面統一介紹 HBase 數據模型中的一些名詞概念:
- 行:每一行代表著一個數據對象,由行鍵來唯一標識,行鍵以字元串的形式存在,而且所有的行都是按照行鍵的字典序進行排序存儲的,按照行鍵排序可以獲得像關係型資料庫主鍵索引一樣的特性。
- 列:由列族和列限定符共同組成。列族需要在表創建時就定義好,表中所有的列都需要組織在列族裡面。列族一旦確定後就不能輕易修改,因為它會影響到 HBase 真實的物理存儲結構,但是列標識符是可以動態增刪的。表中每行都有相同的列族,但是不是每一行的列族都有相同的的列標識,也就是說每行只存儲內容不為空的數據,這是一種稀疏的表結構,可以一定程度上避免數據的冗餘。
- 單元格:每一個行鍵,列鍵(列族 + 列標識)共同組成一個單元,存儲在單元里的數據稱為單元數據。每一個單元數據都具有時間戳,默認由系統指定,也可以由用戶顯示設置。讀取單元數據時,如果時間戳沒有被指定,則默認返回最新的數據。每個單元數據默認的版本數量為3。
HBase 使用了 BigTable 的數據模型,本質上是一個三維的映射表,最基礎的存儲單元是由(行主鍵、列主鍵、時間)三維主鍵定位的,可以看成是 rowkey - columnkey - value 的二級嵌套字典,如果用編程語言來表示其實就是一個 sortedmap。
物理上,列式存儲資料庫以列為單位聚合數據,然後將列值順序地存入磁碟,而行式存儲資料庫則是連續地存儲整行。這其中帶來的好處主要有兩點:
- 對於某些特定的查詢,如果只關心少數幾個列的值,列式資料庫只需要讀取對應數據列的數據,而行式資料庫則需要讀取所有的數據列,這樣可以減少不必要的 IO 操作。而且列式資料庫通常還支持列族,即將多個經常一起訪問的數據列的各個值放在一起,可以從相同的地方一次性讀取多個數據列的值,避免列多個數據列的合併。
- 同一個數據列的數據重複度高,在數據壓縮時有很大的優勢,提高壓縮比有利於在返回結果時降低帶寬的消耗。而且可以針對列式存儲做專門的索引優化,比如點陣圖索引
HBase 集群架構
- HBase 構建在 HDFS 上,在文件系統上增加一層分散式索引層,依賴 Zookeeper 進行伺服器選舉及全局信息維護。
- HBase 中每張表由一個或多個 region (在 BigTable 中稱為子表)組成,region 本質上是以行鍵排序的連續存儲區間,等同於資料庫分區中用的範圍劃分,可以被分配到若干台物理伺服器上均攤負載,是 HBase 中擴展和負載均衡的基本單元。
- HBase 中每一個 region 只能由一台 region 伺服器載入,每一台 region 伺服器可以同時載入多個 region
- 主要由三個部分組成:客戶端程序庫、主控伺服器和多個 region 伺服器。
- 客戶端程序庫:提供 HBase 的訪問介面,應用程序通過客戶端程序庫對表格進行 CRUD 等操作。客戶端程序庫通過 Zookeeper 獲取一些控制信息,但所有表格數據內容都在客戶端與 region 伺服器之間直接傳送
- 主控伺服器:負責整個系統的管理工作,包括 region 的分配、region 伺服器的負載均衡、region 伺服器的故障轉移等
- Region 伺服器:主要負載 region 的數據存儲和管理,同時需要響應客戶端程序的讀寫請求
HBase 單機存儲引擎的實現
基於 LSM 樹實現的單機存儲引擎,LSM 樹的思想非常樸素,就是將對數據的修改增量保存在內存中,達到指定的大小限制後將這些修改操作批量寫入磁碟,讀取時需要合併磁碟中的歷史數據和內存中最近的修改操作。LSM 樹的優勢在於有效地規避了磁碟隨機寫入的問題,但是讀取時可能需要訪問較多的磁碟文件。
HBase 單機存儲引擎主要包括:內存中的 MemTable 和不可變的 MemTable 以及磁碟上的幾種主要文件:當前( Current ) 文件、清單(Manifest ) 文件、操作日誌(Commit Log)文件以及 HFile 文件。
- HFile 文件
- HFile 是 HBase 內部用來存儲數據的文件,主要存儲的是經過排序的鍵值映射結構。每個 HFile 文件劃分為兩塊:數據存儲區和索引區。數據存儲區用來存儲具體的數據,本身又被劃分成小的數據塊,每個塊的默認大小時 64 KB,每次讀取的單位就是一個數據塊。索引區記載了每個數據塊存儲的「行主鍵」範圍及其在 SSTable 中的位置信息。當把 HFile 打開並載入到內存中時,系統將索引區優先載入到內存中,當要讀取一個數據塊時,首先在內存的塊索引中進行二分查找,快速定位某條「行記錄」在 HFile 中的位置信息,之後就可以根據位置信息一次性讀取某個數據塊,找到實際要找的鍵。
- CommitLog
- CommitLog 的主要作用是為了實現在 region 伺服器宕機時,對 MemTable 中的數據進行恢復,保證 MemTable 中的數據不會丟失。
- 讀寫流程
- 寫入數據時,首先將更新命令記入 CommitLog 文件中,之後將更新數據寫入內存的 MemTable 結構中,這樣基本就算完成了寫入操作。寫入操作只涉及一次磁碟順序寫入和一次內存寫入,而且MemTable 採用了維護有序記錄快速插入查找的 SkipList 數據結構,從而實現高速寫入的目的。當 MemTable 里容納的數據超過設定大小時,將內容刷寫到磁碟中,形成一個新的 HFile 文件。這種刷新有兩個功能:首先,可以減少內存消耗量;其次,由於 MemTable 內數據量不會無限制地增長,即使這個 region 伺服器宕機後重啟,那麼系統更加 CommitLog 恢復 MemTable 的速度也會較快。
- 刪除數據時,因為存儲文件時不可被改變的,所以無法通過移除某個鍵值對來簡單地刪除數據。實際上,HBase 是通過做個刪除標誌,表明給定行已被刪除。當檢索的時候,略過這些邏輯上刪除的數據。
- 讀取數據則是兩部分數據合併的結果,一部分是 memstore 中還沒有寫入磁碟的數據,另一部分是磁碟上的存儲文件,每次讀取都需要在內存以及各個 HFile 文件中按照從新到老依次查找,代價較高。
- 合併( compaction )
- 隨著 memstore 中的數據不斷刷寫到磁碟中,會產生越來越多的 SSTable 文件,為了加快讀取速度,HBase 內部會執行合併 ( compaction ) 操作來將多個文件合併成一個較大的文件。合併有兩種類型:minor compaction 和 major compaction。
- Minor compaction 將多個小文件重寫為數量較少的大文件,減少存儲文件的數量,從而增加讀操作的效率。這個過程實際上是個多路歸併的過程。因為 HFile 的每個文件都是經過排序的,所以合併速度很快,只受到磁碟 I/O 性能的影響。
- Major compaction 將一個 region 中一個列族的若干個 HFile 重寫為一個新的 HFile。合併過程中,會略過做了刪除標記的數據,而且對於那些超過版本號限制的數據以及生存時間到期的數據,在重寫數據時就不再寫入磁碟。
與 Cassandra 的比較
- 複製與一致性
- 在 CAP 理論中,HBase 是一個 CP 系統。HBase 系統保證強一致性,同一個時刻同一個子表只能被一台 region server 服務,也就是說,Master 將 region 分配給某個 region server 服務時需要確保沒有其他的 region server 正在服務這個 region。這是通過 ZooKeeper 的互斥鎖機制保證的,region server 啟動時需要獲取 ZooKeeper 互斥鎖,當 region server 出現故障,Master 需要等到 region server 的互斥鎖失效,才能把它上面的 region 遷移到其他的 region server。這也直接導致,在 region server 節點出現故障時部分數據短時間內無法提供讀寫服務。
- Cassandra 則是一個 AP 系統。Cassandra 採用無中心節點的 P2P 設計,增加了系統可擴展性,但同時帶來了一致性問題,本身只保證基本的最終一致性。
推薦閱讀:
※「魔鬼」撒旦(Satan)利用「永恆之藍」漏洞捲土重來 主攻資料庫
※基於協程和非同步IO的NoSQL資料庫AsyncDB正式發布
※Access資料庫應用思維導圖
※企名片-6.13日國內外融資事件清單(42筆)
※設計數據密集型應用-DDIA中文翻譯
TAG:資料庫 |