HBase底層存儲原理

<div id="cnblogs_post_body" class="blogpost-body"><p>理解HBase(一個開源的Google的BigTable實際應用)最大的困難是HBase的<a class="replace_word" title="算法與數據結構知識庫" href="http://lib.csdn.net/base/datastructure" target="_blank">數據結構</a>概念究竟是什麼?首先HBase不同於一般的關係<a class="replace_word" title="MySQL知識庫" href="http://lib.csdn.net/base/mysql" target="_blank">數據庫</a>,它是一個適合於非結構化數據存儲的數據庫.另一個不同的是HBase基於列的而不是基於行的模式.</p>
<p>Google's <a href="http://labs.google.com/papers/bigtable.html">BigTable論文</a> 清楚地解釋了什麼是BigTable:<br>
Bigtable是一個疏鬆的分佈式的持久的多維排序的map,這個map被行鍵,列鍵,和時間戳索引.每一個值都是連續的byte數組.(A
Bigtable is a sparse, distributed, persistent multidimensional sorted
map. The map is indexed by a row key, column key, and a timestamp; each
value in the map is an uninterpreted array of bytes.)</p>
<p><a class="replace_word" title="Hadoop知識庫" href="http://lib.csdn.net/base/hadoop" target="_blank">Hadoop</a> wiki的<a href="http://wiki.apache.org/hadoop/Hbase/HbaseArchitecture">HBase架構</a> 頁面提到:<br>
HBase使用和Bigtable非常相同的數據模型.用戶存儲數據行在一個表裏.一個數據行擁有一個可選擇的鍵和任意數量的列.表是疏鬆的存儲的,因此
用戶可以給行定義各種不同的列.(HBase uses a data model very similar to that of
Bigtable. Users store data rows in labelled tables. A data row has a
sortable key and an arbitrary number of columns. The table is stored
sparsely, so that rows in the same table can have crazily-varying
columns, if the user likes.)</p>
<p>&nbsp;</p>
<p>一、架構思路</p>
<p>&nbsp; &nbsp; Hbase是基於Hadoop的項目,所以一般情況下我們使用的直接就是HDFS文件系統,這裏我們不深談HDFS如何構造其分佈式的文件系統,只需要知 道雖然Hbase中有多個RegionServer的概念,並不意味着數據是持久化在RegionServer上的,事實上,RegionServer是 調度者,管理Regions,但是數據是持久化在HDFS上的。明確這一點,在後面的討論中,我們直接把文件系統抽象爲HDFS,不再深究。</p>
<p>&nbsp;</p>
<p>&nbsp; &nbsp; Hbase是一個分佈式的數據庫,使用Zookeeper來管理集羣。在架構層面上分爲Master(Zookeeper中的leader)和多個RegionServer,基本架構如圖:</p>
<p><br><img src="http://dl.iteye.com/upload/attachment/0076/9504/d05f66d8-c3e6-31c1-b0de-b707435fc25f.png" alt=""></p>
<p>&nbsp; &nbsp; 
在Hbase的概念中,RegionServer對應於集羣中的一個節點,而一個RegionServer負責管理多個Region。一個Region代
表一張表的一部分數據,所以在Hbase中的一張表可能會需要很多個Region來存儲其數據,但是每個Region中的數據並不是雜亂無章
的,Hbase在管理Region的時候會給每個Region定義一個Rowkey的範圍,落在特定範圍內的數據將交給特定的Region,從而將負載分
攤到多個節點上,充分利用分佈式的優點。另外,Hbase會自動的調節Region處在的位置,如果一個RegionServer變得Hot(大量的請求
落在這個Server管理的Region上),Hbase就會把Region移動到相對空閒的節點,依次保證集羣環境被充分利用。</p>
<p>&nbsp;</p>
<p>二、存儲模型</p>
<p>&nbsp; &nbsp; 
有了架構層面的保證,接下來的事情就只是關注於數據的具體存儲了。這裏就是每個Region所承擔的工作了。我們知道一個Region代表的是一張
Hbase表中特定Rowkey範圍內的數據,而Hbase是面向列存儲的數據庫,所以在一個Region中,有多個文件來存儲這些列。Hbase中數據
列是由列簇來組織的,所以每一個列簇都會有對應的一個數據結構,Hbase將列簇的存儲數據結構抽象爲Store,一個Store代表一個列簇。</p>
<p><br><img src="http://dl.iteye.com/upload/attachment/0076/9523/41a6ad6f-7077-3a4e-9257-46bc7948c928.png" alt=""><br>&nbsp; &nbsp; &nbsp;所以在這裏也可以看出爲什麼在我們查詢的時候要儘量減少不需要的列,而經常一起查詢的列要組織到一個列簇裏:因爲要需要查詢的列簇越多,意味着要掃描越多的Store文件,這就需要越多的時間。</p>
<p>&nbsp;</p>
<p>&nbsp; &nbsp; 我們來深入Store中存儲數據的方式。Hbase的實現是用了一種LSM 樹的結構!</p>
<p>LSM樹是由B+樹改進而來,所以我們首先來簡單的看看B+樹。</p>
<p><br><img src="http://dl.iteye.com/upload/attachment/0076/9514/134069a3-720c-3421-8bb0-659aa8cab9df.png" alt=""></p>
<p>


&nbsp;</p>
<p>&nbsp; &nbsp; 
這是一顆簡單的B+樹,含義不言而喻,這裏不多分析,但是這種數據結構並不適合Hbase中的應用場景。這樣的數據結構在內存中效率是很高的,但是
Hbase中數據是存儲在文件中的,如果按照這樣的結構來存儲,意味着我們每一次插入數據都要由一級索引找到文件再在文件中間作操作來保證數據的有序性,
這無疑是效率低下的。所以Hbase採用的是LSM樹的結構,這種結構的關鍵是,每一次的插入操作都會先進入MemStore(內存緩衝區),當
MemStore達到上限的時候,Hbase會將內存中的數據輸出爲有序的StoreFile文件數據(根據Rowkey、版本、列名排序,這裏已經和列
簇無關了因爲Store裏都屬於同一個列簇)。這樣會在Store中形成很多個小的StoreFile,當這些小的File數量達到一個閥值的時
候,Hbase會用一個線程來把這些小File合併成一個大的File。這樣,Hbase就把效率低下的文件中的插入、移動操作轉變成了單純的文件輸出、
合併操作。</p>
<p>&nbsp;</p>
<p>&nbsp; &nbsp; 
由上可知,在Hbase底層的Store數據結構中,每個StoreFile內的數據是有序的,但是StoreFile之間不一定是有序的,Store只
需要管理StoreFile的索引就可以了。這裏也可以看出爲什麼指定版本和Rowkey可以加強查詢的效率,因爲指定版本和Rowkey的查詢可以利用
StoreFile的索引跳過一些肯定不包含目標數據的數據。</p>
<p>&nbsp;</p>
<p><img src="http://dl.iteye.com/upload/attachment/0076/9584/acabc47a-6acc-3630-a5d4-0e1538941177.png" alt=""></p>
<p>&nbsp;</p>
<h1 id="1">HBase vs Cassandra</h1>
<table>
<thead>
<tr><th>&nbsp;</th><th>HBase</th><th>Cassandra</th></tr>
</thead>
<tbody>
<tr>
<td>語言</td>
<td>Java</td>
<td>Java</td>
</tr>
<tr>
<td>出發點</td>
<td>BigTable</td>
<td>BigTable and Dynamo</td>
</tr>
<tr>
<td>License</td>
<td>Apache</td>
<td>Apache</td>
</tr>
<tr>
<td>Protocol</td>
<td>HTTP/REST (also Thrift)</td>
<td>Custom, binary (Thrift)</td>
</tr>
<tr>
<td>數據分佈</td>
<td>表劃分爲多個region存在不同region server上</td>
<td>改進的一致性哈希(虛擬節點)</td>
</tr>
<tr>
<td>存儲目標</td>
<td>大文件</td>
<td>小文件</td>
</tr>
<tr>
<td>一致性</td>
<td>強一致性</td>
<td>最終一致性,Quorum NRW策略</td>
</tr>
<tr>
<td>架構</td>
<td>master/slave</td>
<td>p2p</td>
</tr>
<tr>
<td>高可用性</td>
<td>NameNode是HDFS的單點故障點</td>
<td>P2P和去中心化設計,不會出現單點故障</td>
</tr>
<tr>
<td>伸縮性</td>
<td>Region Server擴容,通過將自身發佈到Master,Master均勻分佈Region</td>
<td>擴容需在Hash Ring上多個節點間調整數據分佈</td>
</tr>
<tr>
<td>讀寫性能</td>
<td>數據讀寫定位可能要通過最多6次的網絡RPC,性能較低。</td>
<td>數據讀寫定位非常快</td>
</tr>
<tr>
<td>數據衝突處理</td>
<td>樂觀併發控制(optimistic concurrency control)</td>
<td>向量時鐘</td>
</tr>
<tr>
<td>臨時故障處理</td>
<td>Region Server宕機,重做HLog</td>
<td>數據回傳機制:某節點宕機,hash到該節點的新數據自動路由到下一節點做 hinted handoff,源節點恢復後,推送回源節點。</td>
</tr>
<tr>
<td>永久故障恢復</td>
<td>Region Server恢復,master重新給其分配region</td>
<td>Merkle 哈希樹,通過Gossip協議同步Merkle Tree,維護集羣節點間的數據一致性</td>
</tr>
<tr>
<td>成員通信及錯誤檢測</td>
<td>Zookeeper</td>
<td>基於Gossip</td>
</tr>
<tr>
<td>CAP</td>
<td>1,強一致性,0數據丟失。2,可用性低。3,擴容方便。</td>
<td>1,弱一致性,數據可能丟失。2,可用性高。3,擴容方便。</td>
</tr>
</tbody>
</table>
<h1 id="2">轉自:https://yq.aliyun.com/articles/25706</h1></div>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章