參考:
http://hi.baidu.com/harry_lime/item/f9ef8487eb022ae9ef083d44
http://www.alidata.org/archives/1509
HBASE初探
從事後臺開發兩年多,近期多有關注分佈式KEY-VALUE存儲系統,就從HBASE開始深入淺出。
簡介
項目名稱 |
語言 |
容錯性 |
持久性存儲介質 |
API協議 |
數據模型 |
文檔 |
贊助商/社區 |
Java |
複製 分區 |
自定義磁盤 |
Custom API, Thrift, Rest |
Bigtable |
A |
Apache, yes |
HBASE是一個分佈式、面向列的開源數據庫,起源於BIGTABLE。它是Apache和Hadoop的子項目,建立於HDFS(hadoop distribute file system)之上。Hbase提供了高可靠性、高性能、列存儲、可伸縮、實時讀寫的服務。
Hbase介於NOSQL(key-value)和RDBMS(Relational Database Management System)之間,支持通過主鍵(row-key)和主鍵的range來訪問(檢索)數據。於hadoop、業界其他分佈式存儲系統類似,hbase依靠橫向擴展,不斷增加廉價的商用服務器,來增加計算和存儲能力。
HBASE適用場景:
1. 數據量大,一個表可以有上億行,上百列
2. 面向列存儲、查詢
3. 稀疏:只存儲存在的列數據,不浪費空間
4. 僅支持單行事務操作,不支持聯合查詢
數據存儲形式
Row-key |
Time tamp |
Column Family2 ="content" |
Column Family2 ="title" |
Column Family2 ="desc" |
|
Column0 |
Column1 |
Column2 |
|||
xx.com |
T6 |
"time:2014-04-01" |
|||
T5 |
"xxx.com" |
||||
T4 |
"xx.com" |
||||
T3 |
"<html>aaaaaaaa…" |
"<tbody>…" |
|||
T2 |
"<htmp>…" |
"<tbody>…" |
|||
Yy.com |
…… |
HBASE以表的形式存儲數據,表中有行(row-key)和列(column)組成,所有的列可分爲若干個列族(column family)。詳細見上表
ROW-KEY
跟NOSQL(KEY-VALUE)系統一樣,HBASE的通過row-key來進行數據訪問,訪問hbase中的數據可以通過下列方式:
1. 指定row-key,訪問對應的行(可制定column family,用於返回結果過濾)
2. 指定row-key對應的range
3. 遍歷全表
Row-key可以是任意字符串,最大長度64KB。Hbase存儲時,row-key保存爲字節數組;表中數據按照row-key的字典序進行排序存儲,所以,設計key時,可以充分利用這一點,講熱點數據存放到一起。
列族
表中每個列,都只股數與某一個列族。相同列族的列存放一起,列名都以列族作爲前綴,訪問控制、硬盤數據和內存的訪問統計都在列族的層面進行;必須在使用表前進行列族定義。
時間戳
時間戳爲64B整型,由HBase在數據寫入時自動補充,或者用戶顯示覆制。如果用戶想避免數據版本衝突,需要保證相同row-key時間戳的唯一性。相同row-key、column family下的多份數據,按照時間戳倒序排列,即最新的數據放在最上面。
Cell
有<row-key, column =(family+lable), version>三元組唯一確定的單元。Cell中數據是以字符串形式存儲。
硬盤數據
table 在行的方向上分割爲多個region。Region按照大小分割,每個表最開始的時候只有一個region,隨着數據的不斷增長,region不斷增大,當region增大到一定的閥值的時候,region會分裂成兩個。隨着行的不斷增長,表就會有越來越多的region。
每個region是hbase分佈式存儲和負載均衡的最小單元;但是在硬盤上並不是最小存儲粒度,它由一個或者多個Store組成,每個store保存一個columns family。每個store 又由一個menstore+0或多個storefile組成。Storefile以hfile形式存儲在HDFS上。
系統架構
Client
支持訪問HBASE,緩衝着部分cache來做訪問加速,如hbase中region的位置信息
Zookeeper
保證任何時候,集羣中只有一個master
存儲所有region的尋址入口
實時監控region service的狀態,並將上下線信息通知master
存儲table和table中的列族信息
Master
1 爲Region server分配region
2 負責region server的負載均衡
3 發現失效的region server並重新分配其上的region
4 GFS上的垃圾文件回收
5 處理schema更新請求
Region Server
1 Region server維護Master分配給它的region,處理對這些region的IO請求
2 Region server負責切分在運行過程中變得過大的region
可以看到,client訪問hbase上數據的過程並不需要master參與(尋址訪問zookeeper和region server,數據讀寫訪問regione server),master僅僅維護者table和region的元數據信息,負載很低。
關鍵模塊流程說明
Region定位
用戶訪問通過zookeeper或者緩存得到row-key所在的region service,再向region server請求訪問數據。
Zookeeper是怎麼存儲key到region的映射關係的呢?下面簡單介紹:
將所有的表的region路由信息(表名、region起始rowkey、時間戳對應的region詳細的信息、region server地址作爲一個路由信息),保存在路由表。表的路由信息也作爲獨立的表,存儲在hbase上,分成二級表:-ROOT-和.META.,它們的數據結構類似:
Rowkey (region name) |
info |
||
Region-info |
server |
serverstartcode |
|
TableName+ startkey(region)+timestamp |
Startkey, endkey,family list, ……其他統計信息 |
Address (管理此region的RegionServer地址) |
其中-ROOT-表數據常駐zookeeper內存中,保存了.META.表的路由信息,且不會進行分裂(只有一個region)。而.META.表保存了整個HBase集羣中所有表的region路由信息,可能會比較大,有多個region,所以是作爲普通表,存儲在某些region service上。爲了加快訪問,.META.表的全部region都保存在內存中。
HBase的設計中-ROOT-表不會太大:假設,.META.表的一行在內存中大約佔用1KB。並且每個region限制爲128MB。那麼上面的三層結構下,集羣可以保存的region數目爲:(128MB/1KB) * (128MB/1KB) = = 2(34)個region = 2(51)B=4PB。
Client會將已經得到的路由信息緩存起來,並不主動失效;只有在region發生了變化後,纔可能需要重新從zookeeper拉去路由。
讀寫過程
讀:處理讀請求時,需要訪問Store中全部的 StoreFile和MemStore,將數據按照row-key進行合併。memstore和storefile中數據都是有序的,且storefile帶有內存索引,所以合併過程比較快。
寫:數據更新時,先寫入HLOG,後寫入memstore(有序)中。
Memstore滿:當memstore寫到一定閥值時,會創建一個新的memstore,並將老的memstore添加到flush隊列中,等待落地成爲一個Hfile,完成後在HLOG中記錄redo point,標誌此時間點前的流水已經持久化。Hfile落地有不做更新。
storeFile文件數滿:當storefile文件數達到閥值時,會進行數據合併操作,將多個storefile合併成一個storefile,合併過程中會進行版本合併和數據刪除。由此可知,HBASE的數據更新、刪除都是異步延後操作。
storeFile單個滿:當storefile單個大小達到閥值後,會進行region分裂(split)操作,即將storefile分成兩個,並且將region 分裂成2個region,老的region會下架,新分裂出來的2個region有master分配到相應到region server上。
HLOG
分佈式存儲系統中需要充分考慮的是容災處理,上述寫流程中,對於單機故障(死機)時,memstore的數據將會丟失,所以使用HLOG記錄memstore中的數據。Region server異常死機後,master通過zookeeper感知到。Master首先會處理遺留的HLOG文件,將log文件根據region進行拆分,放到region目錄下,新的server領導region後,會處理這些log(將此信息從hlog恢復到memstore,後flush到storefile,完成數據恢復)。通過hlog可以重建memstore中未及時落地的數據,
Region管理
任何時刻,一個region只能分配給一個region server。Master中記錄了資源管理信息、和狀態存活信息,即region的使用情況、和分配歸屬於那個region server,和有哪些可用region server。當master收到region申請請求,首先找到未使用的region和可用的region server,master給這個region server發送裝載請求,將此region分配出去。Region server得到請求後,將開始對此region服務。
region server上線
master使用zookeeper來跟蹤region server狀態。當某個region server啓動時,會首先在zookeeper上的server目錄下建立代表自己的文件,並獲得該文件的獨佔鎖。由於master訂閱了server 目錄上的變更消息,當server目錄下的文件出現新增或刪除操作時,master可以得到來自zookeeper的實時通知。因此一旦region server上線,master能馬上得到消息。
region server下線
當region server下線時,它和zookeeper的會話斷開,zookeeper而自動釋放代表這臺server的文件上的獨佔鎖。而master不斷輪詢 server目錄下文件的鎖狀態。如果master發現某個region server丟失了它自己的獨佔鎖,(或者master連續幾次和region server通信都無法成功),master就是嘗試去獲取代表這個region server的讀寫鎖,一旦獲取成功,就可以確定:
1 region server和zookeeper之間的網絡斷開了。
2 region server掛了。
的其中一種情況發生了,無論哪種情況,region server都無法繼續爲它的region提供服務了,此時master會刪除server目錄下代表這臺region server的文件,並將這臺region server的region分配給其它還活着的同志。
如果網絡短暫出現問題導致region server丟失了它的鎖,那麼region server重新連接到zookeeper之後,只要代表它的文件還在,它就會不斷嘗試獲取這個文件上的鎖,一旦獲取到了,就可以繼續提供服務。
其他問題
容錯性
Master容錯:Zookeeper重新選擇一個新的Master
ü 無Master過程中,數據讀取仍照常進行;
ü 無master過程中,region切分、負載均衡等無法進行;
RegionServer容錯:
定時向Zookeeper彙報心跳,如果一旦時間內未出現心跳,Master 將該RegionServer上的Region重新分配到其他RegionServer上,失效服務器上“預寫”日誌由主服務器進行分割並派送給新的RegionServer
Zookeeper容錯:Zookeeper是一個可靠地服務,一般配置3或5個Zookeeper實例
數據容災:數據主要爲region中的memstore和storefile,其中memstore通過HLOG達到故障容災,storefile使用HDFS進行存儲,依賴HDFS進行容災。
訪問接口
暫時未使用
使用場景
大數據量存儲,大數據量高併發操作
需要對數據隨機讀寫操作
讀寫訪問均是非常簡單的操作