HBase是一個分布式的、面向列的開源資料庫,該技術來源于 Fay Chang 所撰寫的Google論文“Bigtable:一個結構化資料的分布式存儲系統”。就像Bigtable利用了Google檔案系統(File System)所提供的分布式資料存儲一樣,HBase在Hadoop之上提供了類似于Bigtable的能力。HBase是Apache的Hadoop 項目的子項目。HBase不同于一般的關系資料庫,它是一個适合于非結構化資料存儲的資料庫。另一個不同的是HBase基于列的而不是基于行的模式。
hadoop家族成員:

Hadoop Common
Hadoop體系最底層的一個子產品,為Hadoop各子項目提供各種工具,如:配置檔案和日志操作等。
Avro
Avro是doug cutting主持的RPC項目,有點類似Google的protobuf和Facebook的thrift。avro用來做以後hadoop的RPC,使hadoop的RPC子產品通信速度更快、資料結構更緊湊。
Chukwa
Chukwa是基于Hadoop的大叢集監控系統,由yahoo貢獻。
HBase
基于Hadoop Distributed File System,是一個開源的,基于列存儲模型的分布式資料庫。
HDFS
分布式檔案系統
Hive
hive類似CloudBase,也是基于hadoop分布式計算平台上的提供data warehouse的sql功能的一套軟體。使得存儲在hadoop裡面的海量資料的彙總,即席查詢簡單化。hive提供了一套QL的查詢語言,以sql為基礎,使用起來很友善。
MapReduce
實作了MapReduce程式設計架構
Pig
Pig是SQL-like語言,是在MapReduce上建構的一種進階查詢語言,把一些運算編譯進MapReduce模型的Map和Reduce中,并且使用者可以定義自己的功能。Yahoo網格運算部門開發的又一個克隆Google的項目Sawzall。
ZooKeeper
Zookeeper是Google的Chubby一個開源的實作。它是一個針對大型分布式系統的可靠協調系統,提供的功能包括:配置維護、名字服務、分布式同步、組服務等。ZooKeeper的目标就是封裝好複雜易出錯的關鍵服務,将簡單易用的接口和性能高效、功能穩定的系統提供給使用者。
架構如下:
Client
HBase Client使用HBase的RPC機制與HMaster和HRegionServer進行通信,對于管理類操作,Client與HMaster進行RPC;對于資料讀寫類操作,Client與HRegionServer進行RPC
Zookeeper
Zookeeper Quorum中除了存儲了-ROOT-表的位址和HMaster的位址,HRegionServer也會把自己以Ephemeral方式注冊到 Zookeeper中,使得HMaster可以随時感覺到各個HRegionServer的健康狀态。此外,Zookeeper也避免了HMaster的單點問題,見下文描述
HMaster
HMaster沒有單點問題,HBase中可以啟動多個HMaster,通過Zookeeper的Master Election機制保證總有一個Master運作,HMaster在功能上主要負責Table和Region的管理工作:
1. 管理使用者對Table的增、删、改、查操作
2. 管理HRegionServer的負載均衡,調整Region分布
3. 在Region Split後,負責新Region的配置設定
4. 在HRegionServer停機後,負責失效HRegionServer 上的Regions遷移
HRegionServer
HRegionServer主要負責響應使用者I/O請求,向HDFS檔案系統中讀寫資料,是HBase中最核心的子產品。
HRegionServer内部管理了一系列HRegion對象,每個HRegion對應了Table中的一個Region,HRegion中由多個HStore組成。每個HStore對應了Table中的一個Column Family的存儲,可以看出每個Column Family其實就是一個集中的存儲單元,是以最好将具備共同IO特性的column放在一個Column Family中,這樣最高效。
HStore
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上。
HLog
HBase中WAL(Write Ahead Log) 的存儲格式,實體上是Hadoop的Sequence File。
在了解了上述 HStore的基本原理後,還必須了解一下HLog的功能,因為上述的HStore在系統正常工作的前提下是沒有問題的,但是在分布式系統環境中,無法避免系統出錯或者當機,是以一旦HRegionServer意外退出,MemStore中的記憶體資料将會丢失,這就需要引入HLog了。每個 HRegionServer中都有一個HLog對象,HLog是一個實作Write Ahead Log的類,在每次使用者操作寫入MemStore的同時,也會寫一份資料到HLog檔案中(HLog檔案格式見後續),HLog檔案定期會滾動出新的,并删除舊的檔案(已持久化到StoreFile中的資料)。當HRegionServer意外終止後,HMaster會通過Zookeeper感覺到,HMaster首先會處理遺留的 HLog檔案,将其中不同Region的Log資料進行拆分,分别放到相應region的目錄下,然後再将失效的region重新配置設定,領取 到這些region的HRegionServer在Load Region的過程中,會發現有曆史HLog需要處理,是以會Replay HLog中的資料到MemStore中,然後flush到StoreFiles,完成資料恢複。
HLog資料存儲
HLog檔案就是一個普通的Hadoop Sequence File,Sequence File 的Key是HLogKey對象,HLogKey中記錄了寫入資料的歸屬資訊,除了table和region名字外,同時還包括 sequence number和timestamp,timestamp是“寫入時間”,sequence number的起始值為0,或者是最近一次存入檔案系統中sequence number。HLog Sequece File的Value是HBase的KeyValue對象,即對應HFile中的KeyValue
HFile資料存儲
HBase中KeyValue資料的存儲格式,HFile是Hadoop的二進制格式檔案,實際上StoreFile就是對HFile做了輕量級包裝,即StoreFile底層就是HFile。
首先HFile檔案是不定長的,長度固定的隻有其中的兩塊:Trailer和FileInfo。Trailer中有指針指向其他資料塊的起始點。
File Info中記錄了檔案的一些Meta資訊,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等。
Data Index和Meta Index塊記錄了每個Data塊和Meta塊的起始點。
Data Block是HBase I/O的基本單元,為了提高效率,HRegionServer中有基于LRU的Block Cache機制。每個Data塊的大小可以在建立一個Table的時候通過參數指定,大号的Block有利于順序Scan,小号Block利于随機查詢。每個Data塊除了開頭的Magic以外就是一個個KeyValue對拼接而成, Magic内容就是一些随機數字,目的是防止資料損壞。後面會詳細介紹每個KeyValue對的内部構造。
HFile裡面的每個KeyValue 對就是一個簡單的byte數組。但是這個byte數組裡面包含了很多項,并且有固定的結構。開始是兩個固定長度的數值,分别表示Key的長度和Value 的長度。緊接着是Key,開始是固定長度的數值,表示RowKey的長度,緊接着是RowKey,然後是固定長度的數值,表示Family的長度,然後是 Family,接着是Qualifier,然後是兩個固定長度的數值,表示Time Stamp和Key Type(Put/Delete)。Value部分沒有這麼複雜的結構,就是純粹的二進制資料了。
邏輯模型:
下面分别說說幾個關鍵概念:
1)行鍵(RowKey)
-- 行鍵是位元組數組, 任何字元串都可以作為行鍵;
-- 表中的行根據行鍵進行排序,資料按照Row key的位元組序(byte order)排序存儲;
-- 所有對表的通路都要通過行鍵 (單個RowKey通路,或RowKey範圍通路,或全表掃描)
2)列族(ColumnFamily)
-- CF必須在表定義時給出
-- 每個CF可以有一個或多個列成員(ColumnQualifier),列成員不需要在表定義時給出,新的列族成員可以随後按需、動态加入
-- 資料按CF分開存儲,HBase所謂的列式存儲就是根據CF分開存儲(每個CF對應一個Store),這種設計非常适合于資料分析的情形
3)時間戳(TimeStamp)
-- 每個Cell可能又多個版本,它們之間用時間戳區分
4)單元格(Cell)
-- Cell 由行鍵,列族:限定符,時間戳唯一決定
-- Cell中的資料是沒有類型的,全部以位元組碼形式存貯
5)區域(Region)
-- HBase自動把表水準(按Row)劃分成多個區域(region),每個region會儲存一個表裡面某段連續的資料;
-- 每個表一開始隻有一個region,随着資料不斷插入表,region不斷增大,當增大到一個閥值的時候,region就會等分會兩個新的region;
-- 當table中的行不斷增多,就會有越來越多的region。這樣一張完整的表被儲存在多個Region 上。
-- HRegion是HBase中分布式存儲和負載均衡的最小單元。最小單元表示不同的HRegion可以分布在不同的HRegionServer上。但一個HRegion不會拆分到多個server上。
HBase 是基于列的資料庫,讓我們看一下關系型資料庫和hbase資料庫存儲的對比。
行式存儲和列式存儲對比:
行式存儲
資料是按行存儲的
沒有索引的查詢使用大量I/O
建立索引和物化視圖需要花費大量時間和資源
面對查詢的需求,資料庫必須被大量膨脹才能滿足性能要求
列式存儲
資料按列存儲——每一列單獨存放
資料即是索引
隻通路查涉及的列——大量降低系統IO
每一列由一個線索來處理——查詢的并發處理
資料類型一緻,資料特征相似——高效壓縮
傳統關系型資料庫(mysql,oracle)資料存儲方式主要如下:
上圖是個很典型的資料儲存方式,我把每條記錄分成3部分:主鍵、記錄屬性、索引字段。我們會對索引字段建立索引,達到二級索引的效果。
但是随着業務的發展,查詢條件越來越複雜,需要更多的索引字段,且很多值都不存在,如下圖:
上圖是6個索引字段,實際情況可能是上百個甚至更多,并且還需要根據多個索引字段刷選。查詢性能越來越低,甚至無法滿足查詢要求。關系型資料裡的局限也開始顯現,于是很多人開始接觸NoSQL。
列族資料庫很強大,很多人就想把資料從mysql遷到hbase,存儲的方式還是跟上圖一樣,主鍵為rowkey。其他各個字段的資料,存 儲一個列族下的不同列。但是想對索引字段查詢就沒有辦法,目前還沒有比較好的基于bigtable的二級索引方案,是以無法對索引字段做查詢。
這時候其實可以轉換下思維,可以把資料倒過來,如下圖:
把各個索引字段的值作為rowkey,然後把記錄的主鍵和屬性值按照一定順序存在對應rowkey的value裡。上圖隻有一個列族,是最簡單的方式。 Value裡的記錄可以設定成定長的byte[],多個記錄集合通過移位快速查詢到。
但是上面隻适合單個索引字段的查詢。如果要同時對多個索引字段查詢,上圖的方式需要求取出所有value值,比如查詢“浙江”and“手機”,需要取出兩個value,再解析出各自的主鍵求交。如果每條記錄的屬性有上百個,對性能影響很大。
列族資料庫資料檔案是按照列族分的。在取資料時,都會把一個列族的所有列資料都取出來,事實上我們并不需要把記錄明細取出來,是以把這部分資料放到了另一個列族下。
接下來是對列族2擴充,列族2儲存更多的列,用來做各種刷選、計算處理。如下圖:
相關内容可以參考:
<a href="http://greatwqs.iteye.com/blog/1838904">http://greatwqs.iteye.com/blog/1838904</a>
1、高速插入