HBase學習總結(3):HBase的資料模型及工作機制,hbase模型
一、HBase資料模型
HBase模式裡的邏輯實體包括:
(1)表(table):HBase用表來組織資料。表名是字串(String),由可以在檔案系統路徑裡使用的字元組成。
(2)行(row):在表裡,資料按行儲存。行由行鍵(rowkey)唯一標識。行鍵沒有資料類型,總是視為位元組數組byte []。
(3)列族(column family):行裡的資料按照列族分組,列族也影響到HBase資料的物理存放,因此,它們必須事前定義並且不輕易修改。表中每行擁有相同列族,儘管行不需要在每個列族裡儲存資料。列族名字是字串(String),由可以在檔案系統路徑裡使用的字元組成。
(4)列限定符(column qualifier):列族裡的資料通過列限定符或列來定位。列限定符不必事前定義,列限定符不必在不同行之間保持一致。就像行鍵一樣,列限定符沒有資料類型,總是視為位元組數組byte []。
(5)單元(cell):行鍵、列族和列限定符一起確定一個單元。儲存在單元裡的資料稱為單元值(value)。值也沒有資料類型,總是視為位元組數組byte []。
(6)時間版本(version):單元值有時間版本。時間版本用時間戳記標識,是一個long。沒有指定時間版本時,目前時間戳作為操作的基礎。HBase保留單元值時間版本的數量基於列族進行配置,預設數量是3個。
HBase的每個資料值使用座標來訪問。一個值的完整座標包括行鍵、列族、列限定符和時間版本。由於把所有座標視為一個整體,因此HBase可以看作是一個索引值(key-value)資料庫。
例如,在《HBase學習總結(2):HBase介紹及其基本操作》(http://blog.csdn.net/zhouzhaoxiong1227/article/details/46682291)中:
(1)表名是“mytable”。
(2)行是“first”、“second”和“third”。
(3)列族是“cf”。
(4)列限定符是“info”、“name”和“nation”。
(5)單元值是“hello hbase”、“zhou”和“China”。
(6)時間戳記是“1435548279711”、“1435548751549”和“1435548760826”。
二、HBase工作機制
1.HBase寫路徑
在HBase中無論是增加新行還是修改已有的行,其內部流程都是相同的。預設情況下,執行寫入時會寫到兩個地方:預寫式日誌(write-ahead log,WAL,也稱HLog)和MemStore。HBase的預設是將寫入動作記錄在這兩個地方,以保證資料持久化。只有當這兩個地方的變化資訊都寫入並確認之後,才認為寫動作完成。寫入過程1所示。
圖1 HBase同時向WAL和MemStore執行寫入
MemStore是記憶體裡的寫入緩衝區,HBase中資料在永久寫入磁碟之前在這裡積累。當MemStore填滿之後,其中的資料會刷寫到硬碟,產生一個HFile。HFile是HBase使用的底層儲存格式。HFile對應於列族,一個列族可以有多個HFile,但一個HFile不能儲存多個列族的資料。在叢集的每個節點上,每個列族有一個MemStore。MemStore產生HFile的過程2所示。
圖2 MemStore產生HFile
如果MemStore還沒有刷寫,伺服器就崩潰了,記憶體中沒有寫入硬碟的資料就會丟失。HBase的應對辦法是在寫動作完成之前先寫入WAL。HBase叢集中每台伺服器維護一個WAL來記錄發生的變化。WAL是底層檔案系統上的一個檔案。直到WAL新記錄成功寫入後,寫動作才會被認為成功完成。這可以保證HBase和支撐它的檔案系統滿足持久性。大多數情況下,HBase使用HadoopDistributed File System(HDFS)來作為底層檔案系統。
如果HBase伺服器宕機,沒有從MemStore裡刷寫到HFile的資料將可以通過回放WAL來恢複。你不需要手工執行。HBase的內部機制中有恢複流程部分來處理。每台HBase伺服器有一個WAL,這台伺服器上的所有表(和它們的列族)共用這個WAL。
值得注意的是,不寫入WAL會在RegionServer故障時增加遺失資料的風險。關閉WAL,出現故障時HBase可能無法恢複資料,沒有刷寫到硬碟的所有寫入資料都會丟失。
2.HBase讀路徑
如果想快速存取資料,通用的原則是資料保持有序並儘可能儲存在記憶體裡。HBase實現了這兩個目標,大多數情況下讀操作可以做到毫秒級。HBase讀動作必須重新銜接持久化到硬碟上的HFile和記憶體中MemStore裡的資料。HBase在讀操作上使用了LRU(最近最少使用演算法)緩衝技術。這種緩衝也叫做BlockCache,和MemStore在一個JVM堆裡。BlockCache設計用來儲存從HFile裡讀入記憶體的頻繁訪問的資料,避免硬碟讀。每個列族都有自己的BlockCache。
掌握BlockCache是最佳化HBase效能的一個重要組成部分。BlockCache中的Block是HBase從硬碟完成一次讀取的資料單位。HFile物理存放形式是一個Block的序列外加這些Block的索引。這意味著,從HBase裡讀取一個Block需要先在索引上尋找一次該Block,然後從硬碟讀出。Block是建立索引的最小資料單位,也是從硬碟讀取的最小資料單位。Block大小按照列族設定,預設值是64KB。根據使用情境你可能會調大或者調小該值。Block變小會導致索引變大,進而消耗更多記憶體;Block變大意味著索引項目變少,索引變小,因此節省記憶體。
從HBase中讀出一行,首先會檢查MemStore等待修改的隊列,然後檢查BlockCache看包含該行的Block是否最近被訪問過,最後訪問硬碟上的對應HFile。整個讀入過程3所示。
圖3 HBase讀入過程
注意,HBase存放某個時刻MemStore刷寫時的快照,一個完整行的資料可能存放在多個HFile中。為了讀出完整行,HBase可能需要讀取包含該行資訊的所有HFile。
3.HBase的合并
刪除命令並不是立即刪除內容,它只是給記錄打上了刪除的標記。就是說,針對那個內容的一條“墓碑”(tombstone)記錄寫入進來,作為刪除的標記。墓碑記錄用來標誌刪除的內容不能在get和scan命令中返回結果。因為HFile檔案是不能改變的,直到執行一次大合并,這些墓碑記錄才會被處理,被刪除記錄佔用的空間才會被釋放。
合并分為兩種:大合并(major compaction)和小合并(minor compaction)。兩種將會重整儲存在HFile裡的資料。小合并把多個小HFile合并產生一個大HFile。因為讀出一條完整的行可能引用很多檔案,限制HFile的數量對於讀效能很重要。執行合并時,HBase讀出已有的多個HFile的內容,把記錄寫入一個新檔案。然後,把新檔案設定為啟用狀態,刪除構成這個新檔案的所有老檔案。HBase根據檔案的號碼和大小決定合并哪些檔案。小合并設計出發點是輕微影響HBase的效能,所以涉及的HFile的數量有上限。這些都可以設定。小合并的示意4所示。
圖4 小合并的
大合并將處理給定region的一個列族的所有HFile。大合并完成後,這個列族的所有HFile合并成一個檔案。可以從Shell中手工觸發整個表(或者特定region)的大合并。這個動作相當耗費資源,不要經常使用。另一方面,小合并是輕量級的,可以頻繁發生。大合并是HBase清理被刪除記錄的唯一機會。因為我們不能保證被刪除的記錄和墓碑標記記錄在一個HFile裡面,而大合并可以確保同時訪問到兩種記錄。
本人公眾號:zhouzxi,請掃描以下二維碼:
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。