1. 概念相關
爲何有HDFS還要用HBase?
- 延遲: Mapreduce編程框架延遲較高,沒法知足大規模數據實時處理應用的需求
- 訪問: HDFS面向批量訪問而不是隨機訪問
爲何用HBase而不用傳統關係型數據庫? / 關係型數據庫和HBase有什麼區別?
- 數據類型: 傳統關係型數據庫有豐富的數據類型,HBase把數據存儲爲未經解釋的字符串
- 數據操做: 關係數據庫包含了豐富的操做,可涉及複雜的多表鏈接,而HBase只有簡單的插入查詢刪除清空等,不涉及表與表的鏈接
- 存儲模式: 關係數據庫基於行存儲,HBase基於列存儲
- 數據索引: 關係數據庫可構建複雜的多個索引以提升檢索效率;HBase只有一個索引:行鍵(RowKey),通過巧妙地設計,經過rowkey索引或掃描,不會使系統慢下來
- 數據維護: 關係數據庫更新會覆蓋原值,HBase則是生成一個新的版本,舊數據依然保留
- 可伸縮性: 關係數據庫很難實現橫向擴展,而HBase可以容易地經過在集羣中增長或減小硬件實現性能地伸縮
HBase架構
![image.png image.png](http://static.javashuo.com/static/loading.gif)
圖1
![image.png image.png](http://static.javashuo.com/static/loading.gif)
圖2數據庫
- 客戶端:客戶端包含訪問HBase的接口,同時在緩存中維護着已經訪問過的Region位置信息,用來加快後續數據訪問過程
- Zookeeper服務器: 能夠幫助選舉出一個Master做爲集羣的總管,並保證在任什麼時候刻總有惟一一個Master在運行,這就避免了Master的「單點失效」問題;保存了記錄了META表的位置(元數據入口地址);
- Master: 主服務器Master主要負責表和Region的管理工做:
–管理用戶對錶的增長、刪除、修改、查詢等操做
–實現不一樣Region服務器之間的負載均衡
–在Region分裂或合併後,負責從新調整Region的分佈
–對發生故障失效的Region服務器上的Region進行遷移
-
- Region服務器 , 負責維護分配給本身的Region,和HDFS交互,Region的拆分(是否拆分由HMaster決定),StoreFile合併,響應用戶的讀寫請求
一些我的理解:編程
- 一個HBase表, 由多個Region組成,這些Region能夠不在一個Region Server上;
- 根據RowKey切分Region,某個或某個連續範圍內的RowKey會被切分到一個Region
- 一個Store 對應 一個列族的數據,但一個列族因爲Region的切分,可能對應多個store
- 尋址過程客戶端只須要詢問Zookeeper服務器,不須要鏈接Master服務器
某個Region Server失效/宕機會怎麼處理
某個Region Server宕機,其元數據信息仍存在,其數據在HDFS上(Store File)也存在副本。那麼HMaster會根據元數據信息,將該Region Server 管理的數據分給其餘Region Server;而Memory Store 中的數據不可恢復,但產生Memory Store數據的操做保存在了HLog中,那麼HMaster還須要把HLog拆分,並把對應得HLog分給對應的Region Server。緩存
HBase 讀寫
讀流程
![image.png image.png](http://static.javashuo.com/static/loading.gif)
- 客戶端向ZK詢問元數據所在的Region Server是哪個
- ZK返回元數據所在的RS
- 客戶端向該RS請求元數據
- 返回元數據,客戶端根據RowKey和元數據找到要RowKey對應數據所在的RS
- 客戶端對該RS發起讀請求
- 該RS先去Block Cache中找RowKey對應的數據,若是不存在,再去MemoryStore中找(MemoryStore的數據最新,因此先找該位置),MemroyStore不存在 再去StoreFile找,找到後把該數據刷寫到Block Cache中,便於下次直接從緩存中讀取,再返回
寫流程
![image.png image.png](http://static.javashuo.com/static/loading.gif)
Flush 刷寫
hbase-default.xml配置文件服務器
- hbase.regionserver.global.memorystore.size: 觸發刷寫到storefile的整個RegionServer最大內存,默認是堆的40%
- optionalcacheflushinterval: RegionServer中任一Region的MemoryStore時間間隔達到該值,觸發刷寫,默認1小時
注意 這兩個刷寫機制會觸發整個RegionServer的全部MemoryStore刷寫架構
- hbase.hregion.memstore.flush.size: 單個region的memory store達到某個上限,會觸發該memory store刷寫,默認128MB
Compacy 合併小文件
由於可能有一些memory store數據量不多的時候被刷寫,所以可能存在刷寫到磁盤的小文件,這就須要定時進行合併負載均衡
- hbase.hregion.majorcompaction: 默認是7天,但該操做很是耗資源,所以生產環境下應該關閉,空閒時手動打開
- hbase.hstore.compactionThreshold: 當一個region的storeFile個數超過必定數量,自動進行合併,默認是3
優化相關
預分區
默認的Region拆分方式是每次根據Region個數的平方 * 128MB 做爲拆分的最大上限,那麼可能致使剛開始的拆分的region很小,後面region很大才會拆分,這樣會致使負載不均衡.
因此須要根據業務需求,根據RowKey設置預分區策略框架
RowKey設計
既然預分區策略和RowKey相關 那麼RowKey的設計也相當重要
通常來講,rowkey要保證惟一性,咱們都會爲它加上一個插入時的時間戳,和一些業務需求經常使用的字段的值
爲了防止數據傾斜,直觀的作法是在RowKey前加上一個隨機數,再根據這個隨機數%預分區數來預分區,保證每一個Region大小基本均衡。函數
但這樣帶來一個問題就是,當須要查詢時,由於咱們沒辦法肯定插入數據時的隨機數,因此咱們須要自定義一個生成哈希值的函數,咱們選取一些字段值通過Hash/MD5獲得一個數,根據這個數%預分區數,將其添加到RowKey前,將其劃分到某個Region。性能
這樣咱們須要查詢時只須要重複這個過程便可獲得其RowKey,再去根據該RowKey讀取數據.優化
除此以外,還要考慮集中性,由於業務有多是集中讀取某一個範圍內的數據,那麼就要根據這個字段集中存儲數據,同時要考慮避免集中帶來的數據傾斜