hbase
HBase是一個分布式的、面向列的開源數據庫,該技術來源於 Fay Chang 所撰寫的Google論文“Bigtable:一個結構化數據的分布式存儲系統”。就像Bigtable利用了Google文件系統(File System)所提供的分布式數據存儲一樣,HBase在Hadoop之上提供了類似於Bigtable的能力。HBase是Apache的Hadoop 項目的子項目。HBase不同於一般的關系數據庫,它是一個適合於非結構化數據存儲的數據庫。另一個不同的是HBase基於列的而不是基於行的模式。
hadoop家族
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的目標就是封裝好復雜易出錯的關鍵服務,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶。
hbase系統架構圖
架構如下:
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部分沒有這么復雜的結構,就是純粹的二進制數據了。
hbase的邏輯模型
邏輯模型:
下面分別說說幾個關鍵概念:
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 是基於列的數據庫,讓我們看一下關系型數據庫和hbase數據庫存儲的對比。
行式存儲和列式存儲對比:
行式存儲
- 數據是按行存儲的
- 沒有索引的查詢使用大量I/O
- 建立索引和物化視圖需要花費大量時間和資源
- 面對查詢的需求,數據庫必須被大量膨脹才能滿足性能要求
列式存儲
數據按列存儲——每一列單獨存放
數據即是索引
只訪問查涉及的列——大量降低系統IO
每一列由一個線索來處理——查詢的並發處理
數據類型一致,數據特征相似——高效壓縮
關系型數據庫到hbase數據存儲的變遷
傳統關系型數據庫(mysql,oracle)數據存儲方式主要如下:
上圖是個很典型的數據儲存方式,我把每條記錄分成3部分:主鍵、記錄屬性、索引字段。我們會對索引字段建立索引,達到二級索引的效果。
但是隨着業務的發展,查詢條件越來越復雜,需要更多的索引字段,且很多值都不存在,如下圖:
上圖是6個索引字段,實際情況可能是上百個甚至更多,並且還需要根據多個索引字段刷選。查詢性能越來越低,甚至無法滿足查詢要求。關系型數據里的局限也開始顯現,於是很多人開始接觸NoSQL。
列族數據庫很強大,很多人就想把數據從mysql遷到hbase,存儲的方式還是跟上圖一樣,主鍵為rowkey。其他各個字段的數據,存 儲一個列族下的不同列。但是想對索引字段查詢就沒有辦法,目前還沒有比較好的基於bigtable的二級索引方案,所以無法對索引字段做查詢。
這時候其實可以轉換下思維,可以把數據倒過來,如下圖:
把各個索引字段的值作為rowkey,然后把記錄的主鍵和屬性值按照一定順序存在對應rowkey的value里。上圖只有一個列族,是最簡單的方式。 Value里的記錄可以設置成定長的byte[],多個記錄集合通過移位快速查詢到。
但是上面只適合單個索引字段的查詢。如果要同時對多個索引字段查詢,上圖的方式需要求取出所有value值,比如查詢“浙江”and“手機”,需要取出兩個value,再解析出各自的主鍵求交。如果每條記錄的屬性有上百個,對性能影響很大。
接下來的變化是解決多索引字段查詢的問題。我們將主鍵字段和屬性字段分開存儲,儲存在不同的列族下,多索引查詢只需要取出列族1下的數據,再去最小集合的列族2里取得想要的值。儲存如下圖:
列族數據庫數據文件是按照列族分的。在取數據時,都會把一個列族的所有列數據都取出來,事實上我們並不需要把記錄明細取出來,所以把這部分數據放到了另一個列族下。
接下來是對列族2擴展,列族2儲存更多的列,用來做各種刷選、計算處理。如下圖:
hbase的ROOT和META表
相關內容可以參考:
http://greatwqs.iteye.com/blog/1838904
hbase適合
1、高速插入