HBase存儲及讀寫原理介紹
一、HBase介紹及其特點
HBase是一個開源的非關係型分散式資料庫,它參考了Google的BigTable建模,實現的程式語言為Java。它是Apache軟體基金會的Hadoop項目的一部分,運行於HDFS文件系統之上,為 Hadoop 提供類似於BigTable 規模的服務。因此,它可以容錯地存儲海量稀疏的數據。
HBase是一個高可靠、高性能、面向列、可伸縮的分散式資料庫,是GoogleBigTable的開源實現,主要用來存儲非結構化和半結構化的鬆散數據。HBase的目標是處理非常龐大的表,可以通過水平擴展的方式,利用廉價電腦集群處理由超過10億行數據和數百萬列元素組成的數據表。
Hadoop HDFS 是無法處理高速隨機寫入和讀取,也無法在不重寫文件的情況下對文件進行修改。HBase 正好解決了 HDFS 的缺點,因為它使用優化的方式快速隨機寫入和讀取。此外,隨著數據呈指數增長,關係資料庫無法提供更好性能去處理海量的數據。HBase提供可擴展性和分區,以實現高效的存儲和檢索。
1.1、海量存儲
Hbase適合存儲PB級別的海量數據,在PB級別的數據以及採用廉價PC存儲的情況下,能在幾十到百毫秒內返回數據。這與Hbase的極易擴展性息息相關。正式因為Hbase良好的擴展性,才為海量數據的存儲提供了便利。
1.2、列式存儲
這裡的列式存儲其實說的是列族存儲,Hbase是根據列族來存儲數據的。列族下面可以有非常多的列,列族在創建表的時候就必須指定。
1.3、極易擴展
Hbase的擴展性主要體現在兩個方面,一個是基於上層處理能力(RegionServer)的擴展,一個是基於存儲的擴展(HDFS)。通過橫向添加RegionSever的機器,進行水平擴展,提升Hbase上層的處理能力,提升Hbsae服務更多Region的能力。
1.4、高並發
由於目前大部分使用Hbase的架構,都是採用的廉價PC,因此單個IO的延遲其實並不小,一般在幾十到上百ms之間。這裡說的高並發,主要是在並發的情況下,Hbase的單個IO延遲下降並不多。能獲得高並發、低延遲的服務。
1.5、稀疏
稀疏主要是針對Hbase列的靈活性,在列族中,你可以指定任意多的列,在列數據為空的情況下,是不會佔用存儲空間的。
二、HBase存儲
2.1 HBase數據模型
2.1.1 與傳統關係型資料庫對比
下圖是針對Hbase和關係型資料庫的基本的一個比較:

1)數據類型:關係資料庫採用關係模型,具有豐富的數據類型和存儲方式, HBase則採用了更加簡單的數據模型,它把數據存儲為未經解釋的字元串。
2)數據操作:關係資料庫中包含了豐富的操作,其中會涉及複雜的多表連接。 HBase操作則不存在複雜的表與表之間的關係,只有簡單的插入、查詢、刪除、 清空等,因為HBase在設計上就避免了複雜的表和表之間的關係。
3)存儲模式:關係資料庫是基於行模式存儲的。HBase是基於列存儲的,每個列族都由幾個文件保存,不同列族的文件是分離的。
4)數據索引:關係資料庫通常可以針對不同列構建複雜的多個索引,以提高數 據訪問性能。HBase只有一個索引——行鍵,通過巧妙的設計,HBase中的所有訪 問方法,或者通過行鍵訪問,或者通過行鍵掃描,從而使得整個系統不會慢下來 。
5)數據維護:在關係資料庫中,更新操作會用最新的當前值去替換記錄中原來 的舊值,舊值被覆蓋後就不會存在。而在HBase中執行更新操作時,並不會刪除數 據舊的版本,而是生成一個新的版本,舊有的版本仍然保留。
6)可伸縮性:關係資料庫很難實現橫向擴展,縱向擴展的空間也比較有限。相反,HBase和BigTable這些分散式資料庫就是為了實現靈活的水平擴展而開發的, 能夠輕易地通過在集群中增加或者減少硬體數量來實現性能的伸縮。
Table(表格)
• 一個HBase表格由多行組成。
Row Key:
• 決定一行數據的唯一標識
• RowKey是按照字典順序排序的。
• Row key最多只能存儲64k的位元組數據。
Column Family列族(CF1、CF2、CF3) & qualifier列:
• HBase表中的每個列都歸屬於某個列族,列族必須作為表模式(schema) 定義的一部分預先給出。如create 『test』, 『course』;
• 列名以列族作為前綴,每個「列族」都可以有多個列成員(column,每個列族中可以存放幾千~上千萬個列);如 CF1:q1, CF2:qw,新的列族成員(列)可以隨後按需、動態加入,Family下面可以有多個 Qualifier,所以可以簡單的理解為,HBase中的列是二級列,也就是說Family是第一級列,Qualifier是第二級列。兩個是父子關係。
• 許可權控制、存儲以及調優都是在列族層面進行的;
• HBase把同一列族裡面的數據存儲在同一目錄下,由幾個文件保存。
• 目前為止HBase的列族能能夠很好處理最多不超過3個列族。
Timestamp時間戳:
• 在HBase每個cell存儲單元對同一份數據有多個版本,根據唯一的時間 戳來區分每個版本之間的差異,不同版本的數據按照時間倒序排序,最新的數據版本排在最前面。
• 時間戳的類型是64位整型。
• 時間戳可以由HBase(在數據寫入時自動)賦值,此時時間戳是精確到毫 秒的當前系統時間。
• 時間戳也可以由客戶顯式賦值,如果應用程式要避免數據版本衝突, 就必須自己生成具有唯一性的時間戳。
Cell單元格:
• 由行和列的坐標交叉決定;
• 單元格是有版本的(由時間戳來作為版本);
• 單元格的內容是未解析的位元組數組(Byte[]),cell中的數據是沒有類型的,全部是位元組碼形式存貯。
• 由{row key,column(=<family> +<qualifier>),version}唯一確定的單元。
2.2 HBase 的架構設計
Client
• 包含訪問HBase的介面並維護cache來加快對HBase的訪問
Zookeeper
• 保證任何時候,集群中只有一個master。HBase 會啟動多個 HMaster,並通過 ZooKeeper 選舉出一個主伺服器
• 存貯所有Region的定址入口。
• 實時監控Region server的上線和下線資訊。並實時通知Master
• 存儲HBase的schema和table元數據
Master
• 為Region server分配region
• 負責Region server的負載均衡
• 發現失效的Region server並重新分配其上的region
• 管理用戶對table的增刪改操作
RegionServer
• Region server負責切分在運行過程中變得過大的region
• Region伺服器負責存儲和維護分配給自己的Region,處理來自客戶端的讀寫請求, 客戶端並不是直接從Master主伺服器上讀取數據,而是在獲得Region的存儲位置資訊後,直接從Region伺服器上讀取數據, 客戶端並不依賴Master,而是通過Zookeeper來獲得Region位置資訊,大多數客戶 端甚至從來不和Master通訊,這種設計方式使得Master負載很小。
HLog(WAL log):
• HStore在系統正常工作的前提下是沒有問題的,但是在分散式系統環境中,無法避免系統出錯或者宕機,因此一旦HRegionServer意外退出,MemStore中的記憶體數據將會丟失,這就需要引入HLog了。每個HRegionServer中都有一個HLog對象,HLog是一個實現Write Ahead Log的類,在每次用戶操作寫入MemStore的同時,也會寫一份數據到HLog文件中,HLog文件定期會滾動出新的,並刪除舊的文件(已持久化到StoreFile中的數據)。當HRegionServer意外終止後,HMaster會通過Zookeeper感知到,HMaster首先會處理遺留的 HLog文件,將其中不同Region的Log數據進行拆分,分別放到相應region的目錄下,然後再將失效的region重新分配,領取 到這些region的HRegionServer在Load Region的過程中,會發現有歷史HLog需要處理,因此會Replay HLog中的數據到MemStore中,然後flush到StoreFiles,完成數據恢復。
Region
• HBase自動把表水平劃分成多個區域(region),每個region會保存一個表裡面某段連續的數據;每個表一開始只有一個region,隨著數據不斷插 入表,region不斷增大,當增大到一個閥值的時候,region就會等分會 兩個新的region(裂變);
• 當table中的行不斷增多,就會有越來越多的region。這樣一張完整的表 被保存在多個Regionserver上。
Memstore 與 storefile
• 一個region由多個store組成,一個store對應一個CF(列族)
• store包括位於記憶體中的memstore和位於磁碟的storefile寫操作先寫入 memstore
• HStore存儲是HBase存儲的核心了,其中由兩部分組成,一部分是MemStore,一部分是StoreFiles。MemStore是Sorted Memory Buffer,用戶寫入的數據首先會放入MemStore,當MemStore滿了以後會Flush成一個StoreFile(底層實現是HFile),當StoreFile文件數量增長到一定閾值,會觸發Compact合併操作,將多個StoreFiles合併成一個StoreFile,合併過程中會進行版本合併和數據刪除,因此可以看出HBase其實只有增加數據,所有的更新和刪除操作都是在後續的compact過程中進行的,這使得用戶的寫操作只要進入記憶體中就可以立即返回,保證了HBase I/O的高性能。當StoreFiles Compact後,會逐步形成越來越大的StoreFile,當單個StoreFile大小超過一定閾值後,會觸發Split操作,同時把當前Region Split成2個Region,父Region會下線,新Split出的2個孩子Region會被HMaster分配到相應的HRegionServer上,使得原先1個Region的壓力得以分流到2個Region上。
三、Hbase的數據讀寫原理
3.1 Hbase定址原理
3.1.1 -ROOT-表和.META.表的介紹
HBase用-ROOT-表記錄.META.表的位置資訊(即元數據資訊),而.META.表記錄了用戶表Region的位置資訊。為了定位.META.表中各個Region的位置資訊,把.META.表中所有Region的元數據保存在-ROOT-表中,最後由Zookeeper記錄-Root-表的位置資訊。所以客戶端Client要先訪問ZK獲取-ROOT-表的位置,然後訪問-ROOT-表獲取.META.表的位置,最後根據.META.表中的資訊確定用戶數據存放的位置。
3.2 -ROOT-表結構
HBase的用-ROOT-表來記錄.META.的Region資訊,就和.META.記錄用戶表的Region資訊一模一樣。-ROOT-只會有一個Region。這麼一來Client端就需要先去訪問-ROOT-表。所以需要知道管理-ROOT-表的RegionServer的地址。這個地址被存在ZooKeeper中。默認的路徑是:/hbase/root-region-server
3.3 META.表結構

3.4 兩個表的關係
HBase的所有Region元數據被存儲在.META.表中,隨著Region的增多,.META.表中的數據也會增大,並分裂成多個新的Region。為了定位.META.表中各個Region的位置,把.META.表中所有Region的元數據保存在-ROOT-表中,最後由Zookeeper記錄-ROOT-表的位置資訊。所有客戶端訪問用戶數據前,需要首先訪問Zookeeper獲得-ROOT-的位置,然後訪問-ROOT-表獲得.META.表的位置,最後根據.META.表中的資訊確定用戶數據存放的位置,如下圖所示。
-ROOT-表永遠不會被分割,它只有一個Region,這樣可以保證最多只需要三次跳轉就可以定位任意一個Region。為了加快訪問速度,.META.表的所有Region全部保存在記憶體中。客戶端會將查詢過的位置資訊快取起來,且快取不會主動失效。如果客戶端根據快取資訊還訪問不到數據,則詢問相關.META.表的Region伺服器,試圖獲取數據的位置,如果還是失敗,則詢問-ROOT-表相關的.META.表在哪裡。最後,如果前面的資訊全部失效,則通過ZooKeeper重新定位Region的資訊。所以如果客戶端上的快取全部是失效,則需要進行6次網路來回,才能定位到正確的Region。
3.5 讀流程
1. Client訪問Zookeeper,查找-ROOT-表,獲取.META.表資訊。
2. 從.META.表查找,獲取存放目標數據的Region資訊,從而找到對應的RegionServer。
3. 通過RegionServer獲取需要查找的數據。
4. Regionserver的記憶體分為MemStore和BlockCache兩部分,MemStore主要用於寫數據,BlockCache主要用於讀數據。讀請求先到MemStore中查數據,查不到就到BlockCache中查,再查不到就會到StoreFile上讀,並把讀的結果放入BlockCache。
讀取過程:client–>Zookeeper–>-ROOT-表–>META表–>RegionServer–>Region–>client
3.6 寫流程
1.Client通過Zookeeper調度獲取表的元數據資訊;
2.Cilent通過rpc協議與RegionServer交互,通過-ROOT-表與.META.表找到對應的對應的Region;
3.將數據寫入HLog日誌中,如出現意外可以同通過HLog恢復資訊;
4.將數據寫入Region的MemStore中,當MemStore達到閾值開始溢寫,將其中的數據Flush成一個StoreFile;
5.MemStore不斷生成新的StoreFile,當StoreFile的數量到達閾值後會出發Compact合併操作,將多個StoreFile合併成一個StoreFile;
6.StoreFile文件會不斷增大,當達到閾值後會出發Split操作,把當前的Region且分為兩個新的Region。父Region會下線,兩個子Region會被HMaster分配到相應的RegionServer。
可以看出HBase只有增添數據,所有的更新和刪除操作都是在後續的Compact歷程中舉行的,使得用戶的寫操作只要進入記憶體就可以立刻返回,實現了HBase I/O的高性能。
3.7 快取的刷新
•系統會周期性地把MemStore快取里的內容刷寫到磁碟的StoreFile文 件中,清空快取,並在Hlog裡面寫入一個標記
•每個Region伺服器都有一個自己的HLog 文件,每次啟動都檢查該文 件,確認最近一次執行快取刷新操作之後是否發生新的寫入操作;如果發現更新,則先寫入MemStore,再刷寫到StoreFile,最後刪除舊的Hlog文件,開始為用戶提供服務
參考文章:
//archive.apache.org/dist/hbase/ hbase各版本
//www.jianshu.com/p/e3b764871c68
//blog.csdn.net/yyl424525/article/details/77505749
//baike.baidu.com/item/HBase/7670213?fr=aladdin
//www.jianshu.com/p/d27b31808c8a hbase shell操作