HBase 初學HBase的幾個問題

1. 什麼是HBase?

HBase,是Hadoop Database,是一個高可靠性、高性能、面向列、可伸縮的分佈式存儲系統。使用HBase技術可以在廉價的PC服務器上搭建起大規模結構化的存儲集羣。它底層的文件系統使用HDFS,使用Zookeeper來管理集羣的HMaster和各Region server之間的通信,監控各Region server的狀態,存儲各Region的入口地址等。

2.何時用HBase?

首先想想傳統的關係型數據庫都有哪些特點,大概的特點有:

  1. 支持事務,ACID(原子性、一致性、隔離性和持久性)特性;
  2. 行式存儲;
  3. SQL語句使用起來比較方便;
  4. 支持索引、視圖等;

接下來我們考慮一個場景:我們想要構建一個社交網站,我們可能會選擇易於操作的LAMP(Linux、Apache、Mysql、PHP)模型來快速的搭建一個原型。隨着用戶數的不斷增加,每天有越來越多的人開始訪問,這時候,共享的數據庫服務器壓力會越來越大,可以選擇增加應用服務器,但因爲這些應用服務器共享中央數據庫,所以,隨着數據庫的CPU和I/O負載升高,這種方案勢必不可長久。

這時候,我們可能會增加從服務器,以便並行讀取,將讀寫分離。這樣做是因爲考慮到用戶訪問產生的讀次數比寫入次數更多,但是如果用戶數目增加很快,產生的內容越來越多,導致讀寫數目相差沒那麼大,這種方案也就不能長久。

接下來的常見做法就是增加緩存,比如使用Memcached。這樣,讀操作存入到內存中的數據庫系統中,但又沒辦法保證數據一致性,因爲用戶更新數據到數據庫,而數據庫不會主動更新緩存中的數據,而且,這種方案只能解決讀請求的壓力,對於寫請求,還是沒有解決。所以需要更多的服務器,更快的磁盤,會導致硬件成本快速升高。

而且,隨着用戶的增多,網站功能勢必增加,業務功能都會使用sql語句進行查詢,而表數據過多會導致join操作變慢,所以會不得不採用一些逆範式的方式來設計數據庫,這樣導致無法使用存儲過程。而且,數據過大時,索引的效果也沒那麼強了。因爲索引也會變得很大。

這時候應該怎麼辦?有些人採用了數據庫分區的方式,將數據拆分。但是大規模的拆分將導致大量複製操作,帶來大量的I/O損耗。所以這種方式也不一定好。

03年,谷歌發表了一片論文叫做《The Google File System》,這個文件系統簡稱GFS,該文件系統中的數據在節點中冗餘存儲,即使一臺服務器發生故障,也不會影響數據可用性。但是,GFS只適合存儲少量非常大的文件,不適合存儲數量衆多的小文件,因爲文件的元信息存儲在主節點的內存中,文件越多,主節點壓力越大。經過Google的深入研究,在06年,發表了另外一篇重量級論文《BigTable:A Distributed Storage System for Structed Data》。HBase就是BigTable的開源實現,當然,也建立在HDFS(GFS的開源實現)和Hadoop(MapReduce的開源實現)、Zookeeper(Chubby的開源實現)的基礎上。

何時用HBase呢?在下面幾種情況下,可以考慮使用HBase替代關係數據庫:

  1. 系統需要適應不同種類的數據格式和數據源,不能預先嚴格定義模式,需要處理大規模數據;
  2. 不強調數據之間的關係,所要存儲的數據是半結構化或非結構化的;
  3. 數據非常稀疏;
  4. 想要更好的進行擴展;

比如谷歌就將BigTable用來存儲網頁的索引數據,索引數據就很好的滿足了上面的幾點要求。

和Hive,Pig的區別?

  1. HBase是低延遲、非結構化和麪向編程的,而Hive是高延遲、結構化和麪向分析的;
  2. Hive本身不存儲和計算數據,它完全依賴與HDFS和MapReduce,Hive中的表是邏輯表;
  3. HBase通過組織起節點內所有機器的內存,提供一個超大的內存Hash表,它需要在磁盤和內存組織自己的數據結構,HBase中的表是物理表;
  4. 如果是全表掃描,就用Hive+Hadoop,如果是索引訪問,就用HBase+Hadoop。
  5. Hive主要用於靜態的結構以及需要經常分析的工作;
  6. Pig相比Hive相對輕量,它主要的優勢是相對比於直接使用Hadoop Java APIs可大幅消減代碼量;
  7. Hive和Pig都可以與HBase組合使用,Hive和Pig還爲HBase提供了高層語言支持,使得在HBase上進行數據統計處理變得非常簡單。

HBase的結構?

1)表、行、列和單元格

先做一個簡單的總結:最基本的單位是列(column),一列或者多列組成一行(row),並且由唯一的行鍵(row key)來確定存儲。一個表中有很多行,每一列可能有多個版本,在每一個單元格(Cell)中存儲了不同的值。

HBase的行與行之間是有序的,按照row key的字典序進行排序,行鍵是唯一的,在一個表裏只出現一次,否則就是在更新同一行,行鍵可以是任意的字節數組。一行由若干列組成,其中的某些列又可以構成一個列族(column family),一個列族的所有列存儲在同一個底層的存儲文件裏,這個文件稱之爲HFile。

列族需要在創建表的時候就定義好,數量也不宜過多。列族名必須由可打印字符組成,創建表的時候不需要定義好列。對列的引用格式通常爲family:qualifier,qualifier也可以是任意的字節數組。同一個列族裏qualifier的名稱應該唯一,否則就是在更新同一列,列的數量沒有限制,可以有數百萬個。列值也沒有類型和長度限定。HBase會對row key的長度做檢查,默認應該小於65536。

一個可視化的HBase表如下:

這裏寫圖片描述

Timestamp代表時間戳,默認由系統指定,用戶也可以顯示設置。使用不同的時間戳來區分不同的版本。一個單元格的不同版本的值按照時間戳降序排列在一起,在讀取的時候優先取最新的值。用戶可以指定每個值能保存的最大版本數,HBase-0.96版本默認的最大版本數爲1。

HBase的存取模式如下(表,行鍵,列族,列,時間戳)-> 值。即一個表中的某一行鍵的某一列族的某一列的某一個版本的值唯一。

行數據的存取操作是原子的,可以讀取任意數目的列。目前還不支持跨行事務和跨表事務。

同一列族下的數據壓縮在一起,訪問控制磁盤和內存都在列族層面進行。

2)自動分區

HBase中擴展和負載均衡的基本單元稱作region,region本質上是以行鍵排序的連續存儲空間。如果region過大,系統就會把它們動態拆分,相反的,就把多個region合併,以減少存儲文件數量。

一個表最開始只有一個region,用戶開始向表中插入數據時,系統會檢查region大小,確保不會超過配置的最大值,如果超過,會從region中行鍵的中間值一分爲二,將該region分爲大小大致相等的兩個region。

注意,每個region只能由一個region server加載,每一臺region服務器可以同時加載多個region。下圖展示了一個表,該表實際上是由很多region server加載的region集合組成的邏輯視圖。

這裏寫圖片描述

3)HBase存儲格式

HFile:HBase中KeyValue數據的存儲格式。HFile是Hadoop的二進制格式文件。

HLog:HBase中WAL(Write-Ahead-Log,預寫式日誌)文件的存儲格式,物理上是Hadoop的Sequence File。

HFile的格式如下圖:

這裏寫圖片描述

HFile文件的長度可變,唯一固定的是File Info和Trailer。Trailer存儲指向其他塊的指針,它在持久化數據到文件結束時寫入的,寫入後,該文件就會變成不可變的數據存儲文件。數據塊(data blocks)中存儲key-values,可以看做是一個MapFile。當block關閉操作時,第一個key會被寫入index中,index文件在hfile關閉操作時寫入。

KeyValue的具體格式如下圖:

這裏寫圖片描述

上圖中,keytype有四種類型,分別是Put、Delete、 DeleteColumn和DeleteFamily。RowLength爲2個字節,Row長度不固定,ColumnFamilyLength爲2個字節,ColumnFamily長度不固定,ColumnQualifier長度不固定,TimeStamp爲4個字節,KeyType爲1個字節。之所以不記錄ColumnQualifier的長度是因爲可以通過其他字段計算得到。

4 ) WAL(預寫式日誌)

region server會將數據保存到內存,直到積攢到足夠多的數據再將其刷寫到磁盤,這樣可避免很多小文件。但此時如果發生斷電或其他故障,存儲在內存中的數據沒來得及保存到磁盤,就會出現數據丟失情況。WAL能解決這個問題。每次更新(編輯)都會寫入日誌,只有日誌寫入成功後纔會告知客戶端寫入成功,然後服務器按需批量處理內存中的數據。

如果服務器崩潰,region server會回訪日誌,使得服務器恢復到服務器崩潰前的狀態。下圖顯示了寫入過程:

這裏寫圖片描述

  • 所有的修改都會先保存到WAL,然後再傳給MemStore。整個過程是這樣的:
  • 客戶端啓動一個操作來修改數據,比如Put。每次修改都封裝到一個KeyValue對象實例中,通過RPC調用發送出去。這些調用會發送給含有匹配region的Region Server;
  • KeyValue實例到達後,它們會被分配到管理對應行HRegion實例,數據被寫入WAL,然後被放入實際擁有記錄的MemStore中;
  • 當MemStore達到一定大小或經歷一個特定時間,數據會異步的連續的寫入到文件系統中(HFile)。
  • 如果寫入過程出現問題,WAL能保證數據不丟失,因爲WAL日誌HLog存儲在HDFS上。其他region server可以讀取日誌文件並回放修改,恢復數據。

5)HBase系統架構

HBase架構包括HBase Client、Zookeeper、HMaster、HRegionServer、HStore存儲幾個部分。下面一一敘述。一個大體的架構圖如下:

這裏寫圖片描述

a)HBase Client

HBase Client使用HBase的RPC機制與HMaster和HRegionServer進行通信。對於管理類操作(如建表,刪表等),Client和HMaster進行RPC;對於數據讀寫類操作,Client和HRegionServer進行RPC。

b)Zookeeper

一個分佈式的,開放源碼的分佈式應用程序協調服務,分佈式應用程序可以基於它實現同步服務,配置維護和命名服務等。它是Chubby的開源實現。
Zookeeper Quorum中除了存儲了-ROOT-表的地址和Master的地址,RegionServer也會把自己註冊到Zookeeper中,使Master可以隨時感知到各個RegionServer的健康狀態。

c)HMaster

  • 管理用戶對Table的增、刪、改、查操作;
  • 管理HRegionServer的負載均衡,調整Region分佈;
  • 在Region Split後,負責新Region的分配;
  • 在HRegionServer停機後,負責失效HRegionServer上的Regions遷移。

d)HRegionServer

  • 主要負責響應用戶I/O請求,向HDFS文件系統中讀寫數據,是HBase中最核心的模塊;
  • 當用戶更新數據的時候會被分配到對應的HRegion服務器上提交修改,這些修改顯示被寫到MemStore寫緩存和服務器的Hlog文件裏面。在操作寫入Hlog之後,commit()調用纔會將其返回給客戶端;
  • 在讀取數據的時候,HRegion服務器會先訪問BlockCache讀緩存,如果緩存裏沒有改數據,纔會回到Hstores磁盤上面尋找,每一個列族都會有一個HStore集合,每一個HStore集合包含很多HstoreFile文件。

e)特殊的表

-ROOT- 表和.META.表是兩個比較特殊的表。.META.記錄了用戶表的Region信息,.META.可以有多個regoin。-ROOT-記錄了.META.表的Region信息,-ROOT-只有一個region,Zookeeper中記錄了-ROOT-表的location。具體如下:

這裏寫圖片描述

爲何HBase速度很快?

HBase能提供實時計算服務主要原因是由其架構和底層的數據結構決定的,即由LSM-Tree(Log-Structured Merge-Tree) + HTable(region分區) + Cache決定——客戶端可以直接定位到要查數據所在的HRegion server服務器,然後直接在服務器的一個region上查找要匹配的數據,並且這些數據部分是經過cache緩存的。

前面說過HBase會將數據保存到內存中,在內存中的數據是有序的,如果內存空間滿了,會刷寫到HFile中,而在HFile中保存的內容也是有序的。當數據寫入HFile後,內存中的數據會被丟棄。

HFile文件爲磁盤順序讀取做了優化,按頁存儲。下圖展示了在內存中多個塊存儲並歸併到磁盤的過程,合併寫入會產生新的結果塊,最終多個塊被合併爲更大塊。

這裏寫圖片描述

多次刷寫後會產生很多小文件,後臺線程會合並小文件組成大文件,這樣磁盤查找會限制在少數幾個數據存儲文件中。HBase的寫入速度快是因爲它其實並不是真的立即寫入文件中,而是先寫入內存,隨後異步刷入HFile。所以在客戶端看來,寫入速度很快。另外,寫入時候將隨機寫入轉換成順序寫,數據寫入速度也很穩定。

而讀取速度快是因爲它使用了LSM樹型結構,而不是B或B+樹。磁盤的順序讀取速度很快,但是相比而言,尋找磁道的速度就要慢很多。HBase的存儲結構導致它需要磁盤尋道時間在可預測範圍內,並且讀取與所要查詢的rowkey連續的任意數量的記錄都不會引發額外的尋道開銷。比如有5個存儲文件,那麼最多需要5次磁盤尋道就可以。而關係型數據庫,即使有索引,也無法確定磁盤尋道次數。而且,HBase讀取首先會在緩存(BlockCache)中查找,它採用了LRU(最近最少使用算法),如果緩存中沒找到,會從內存中的MemStore中查找,只有這兩個地方都找不到時,纔會加載HFile中的內容,而上文也提到了讀取HFile速度也會很快,因爲節省了尋道開銷。

HBase常用操作:

  • List;
  • Create;
  • Put;
  • Scan;
  • Get;
  • Delete;
  • Disable;
  • Drop;