在HBase中, 從邏輯上來說數據大概就長這樣:json
單從圖中的邏輯模型來看, HBase 和 MySQL 的區別就是:數據結構
這看着感受也沒有那麼太大的區別呀, 它解決了 MySQL 的那些問題呢? 每個新事物的出現, 都是爲了解決本來存在的問題.併發
那麼他是如何解決這些問題的呢? 他的數據是如何進行存儲的呢?app
在介紹其物理結構以前, 要先簡單提一下 LSM 樹異步
和 MySQL 所使用的B+樹同樣, 也是一種磁盤數據的索引結構. B+樹是一種對讀取友好的存儲結構, 可是當大量寫入的時候, 好比日誌信息, 由於涉及到隨機寫入, 就顯得捉襟見肘了.分佈式
而LSM樹就是針對這種大量寫入的場景而提出的. 他的中文名字叫: 日誌結構合併樹. 文件存儲的是對數據的修改操做, 數據會 append 但不會去修改原有的數據. 是順序寫入操做.性能
可是, 若是無論不顧的將全部的操做都順序寫入了, 那讀取數據的時候沒有任何根據, 須要掃描全部操做才能讀到. LSM 樹的作法是, 先在內存中維護一份小的有序的數據(內存不存在隨機讀寫的問題), 當這份數據超過必定大小的時候, 將其整個放入磁盤中.優化
這樣, 磁盤中就存在不少個有序的文件了, 可是會有大量的小文件, 讀取數據時要依次查找, 致使讀取性能下降. 這時就須要對多個小文件進行多路歸併合成一個文件來優化讀取的性能.日誌
至此, 基本就是LSM 樹的所有思想了.code
在HBase中, 數據的存儲就使用了 LSM 樹進行存儲. 其中每一條數據都是一條操做記錄. 那麼在HBase實現中的部份內容以下.
內存有序結構的實現
經過跳錶來維護內存中的有序結構, 當一個跳錶裝滿以後, 將禁止新的寫入操做並將其 push 到磁盤中, 同時開一個新的數據結構來接收新到的操做請求.
每條數據的存儲內容
存儲了一個KV 鍵值對, 其中的 V 就是咱們寫入的值, 而這個 key 由如下部分組成:
整個列表是 key 的順序列表. 其排序規則以下:
按照這個順序進行讀取指定 row key 的某一列數據時, 最早拿到的數據就是最新的版本, 如果 delete 操做, 說明最後執行了刪除操做, 即便後面有數據, 最新數據也是空.
磁盤文件的結構
由三部分組成:
按照這個結構, 用戶在進行指定row_key 讀取的時候, 每一個文件的操做以下:
先簡單回顧一下行式存儲和列式存儲.
行式存儲
行式存儲, 將一行數據存儲在一塊兒, 一行數據寫完了纔會寫下一行. 例如典型的 MySQL.
行式存儲在讀取一行數據的時候是比較快的, 但若是讀取的是某一列數據, 也須要將整行讀取到內存中進行過濾.
列式存儲
與行式存儲相對應的就是列式存儲, 既將一列數據存儲在一塊兒, 不一樣列的數據分別存儲.
列式存儲對於只讀取某一列比較友好, 但相對的, 若是要讀取多列數據, 須要讀取屢次並進行合併.
列族式存儲
而 HBase 中選用了一種折中的方案, 列族式存儲, 將列族放到一塊兒存儲, 不一樣列族分別存儲.
那麼也就是說, 若是一個表有多個列族, 每一個列族下只有一列, 那麼就等同於列式存儲
若是一個表只有一個列族, 該列族下有多個列, 那麼就等同與行式存儲.
HBase 會將一張表同一列族的數據, 分配到同一個 region 上, 這個region 分配在集羣中的某一個 regionServer. 全部的 region 存儲在表: hbase:meta 表中, 表結構以下:
表不一樣列含義以下:
簡單瞭解了HBase的數據落盤格式, 也大概解釋 HBase 的不少疑惑, 好比: