一、概述
1.1 定義
HBase – Hadoop Database,是一個高可靠性、高性能、面向列、可伸縮、實時讀寫的分佈式數據庫。
1.2 優點&缺點(與關係型數據庫對比)
- 優點
- 海量存儲
- 良好的擴展性
- 稀疏性
- 高性能
- 多版本
- TTL
- 缺點
- 不支持複雜的聚合運算(Join、GroupBy等)
- 沒有二級索引 rowkey--設計
- 不支持跨行事務
1.3 版本變遷
本課程採用的版本是1.4.10,目前HBase社區推薦的最新穩定版本
1.4 數據模型
- 邏輯視圖
- 邏輯圖
- 使用關係型數據庫的概念來描述HBase
- namespace:名稱空間,組織表。
- table:表,一個表包含多行數據。
- row:行,一行數據包含一個唯一標識rowkey和多個 column。
- column
- column family(列簇):創建表的時候指定
- column qualifier(列名):可以動態添加
- 使用方式:family:qualifier
- timestamp:時間戳,每個cell在寫入HBase的時候都會默認分配一個時間戳作為該cell的版本。
- cell:單元格,存儲具體數據
- 物理視圖
- 列簇式存儲
- 同一列簇存儲在同一目錄下
- 同一列存儲在同一個文件中
- 存儲格式:多維稀疏排序Map
- key的構成:rowkey+family+qualifier+type+timestamp
- value的構成:字節形式存儲
1.5 簡單物理結構
- 客戶端
- 提供訪問接口
- Zookeeper
- Master高可用
- 管理核心元數據
- 分佈式鎖
- Master
- 處理用戶的管理請求
- 管理集群RegionServer
- 清理過期日誌以及文件
- RegionServer
- 響應用戶IO請求,是HBase中最核心的模塊
- HDFS
- HBase內部封裝了一個名為DFSClient的HDFS客戶端組件,負責對HDFS的實際數據進行讀寫
二、相關組件
2.1 ZooKeeper
- 概念
- 高性能、分佈式的分佈式應用程序的協調服務。
- 是一個樹形目錄服務
- 提供功能
- 配置管理
- 分佈式鎖
- 集群管理
- ZooKeeper集群
- 一般由奇數個(3個或者5個)節點構成
- 容災能力:(n-1)/2,過半服務可用,整體服務就可用
- HBase中ZooKeeper核心配置
hbase.zookeeper.quorum
nn1.hadoop,nn2.hadoop,dn1.hadoop
hbase.zookeeper.property.clientPort
2181 - ZooKeeper存儲的HBase信息說明
data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
節點名稱說明
- Inspector軟件查看數據
2.2 HDFS
- HDFS在HBase系統中作用
- HBase-HDFS體系是典型的計算存儲分離架構。
- HBase本身不存儲文件,它只規定文件的格式及文件內容,實際存儲由HDFS文件實現
- HBase不提供機制保證存儲數據的高可靠,數據的高可靠有HDFS的多副本機制保證
- HBase在HDFS中的目錄結構
le data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
三、安裝部署
3.1 本地/單機模式
- 本地模式不依賴於HDFS存儲,將文件存儲到操作系統本地目錄。
3.2 偽分佈式
- 即可以運行在本地文件系統上也可以運行在HDFS。
- 所有進程運行在同一個節點(機器)上,不同進程運行在不同的JVM當中。
3.3 完全分佈式
- 進程運行在多個服務器集群中。
- 分佈式依賴於HDFS系統,因此佈署HBase之前一定要有一個正常工作的HDFS集群。
3.4 HA模式
- 在完全分佈式的基礎上達到HMaster的高可用。
- 集群規劃:
nn1.hadoopnn2.hadoopdn1.hadoopdn2.hadoopdn3.hadoop
3.5 HA模式安裝步驟
- 軟件環境
- JDK:1.8
- ZooKeeper:3.4.8
- Hadoop:2.7.4
- HBase:1.4.10
- 解壓安裝文件
- 創建軟連接
- 配置環境變量
- 修改配置文件
- hbase-site.xml
hbase.cluster.distributed
true
hbase.rootdir
hdfs://ns1/hbase
hbase.master.port
60000
hbase.tmp.dir
/data/hbase
hbase.zookeeper.quorum
nn1.hadoop,nn2.hadoop,dn1.hadoop
hbase.zookeeper.property.clientPort
2181
hbase.zookeeper.property.dataDir
/data/zookeeper - hbase-env.sh
# JDK
export JAVA_HOME=/usr/bin/java
# hbase 安裝目錄下創建logs目錄
export HBASE_LOG_DIR=${HBASE_HOME}/logs
# hbase 安裝目錄下創建pids目錄
export HBASE_PID_DIR=${HBASE_HOME}/pids
# 使用外部zk,true表示使用hbase自帶的zk
export HBASE_MANAGES_ZK=false - regionservers
dn1.hadoop
dn2.hadoop
dn3.hadoop
- 拷貝Hadoop的hdfs-site.xml和core-site.xml文件到HBase的conf目錄
- 分發HBase文件
3.6 集群的啟動和關閉
- 啟動集群
# 啟動HBase
start-hbase.sh 或者 hbase-daemon.sh start master/regionserver
# 啟動備用HMaster
hbase-daemon.sh start master - 關閉集群
# 關閉備用HMaster
hbase-daemon.sh stop master
# 關閉HBase
stop-hbase.sh
3.7 HMaster的高可用測試
- 測試步驟
- 結束HMaster進程
- 訪問集群看是否可以正常使用
3.8 HBase的WebUI
- 相關配置
hbase.master.info.port
16010
1.0版本後默認配置為16010
四、客戶端-Shell
4.1 基礎命令
- hbase shell 進入hbase命令行界面
- 常用基礎命令
le data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
4.2 DDL
- 操作namespace
le data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
- 兩個內置的預定義的namespace
- hbase:系統namespace,用於包含hbase的內部表
- default:所有未指定namespace的表都自動進入該namespace
le data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
4.3 DML
- 操作table中數據
le data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
4.4 查詢
- 查詢table中數據
le data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
五、客戶端-API
5.1 API基礎
- maven依賴
org.apache.hbase
hbase-client
1.4.8
jdk.tools
jdk.tools - API 連接HBase
- 創建HBaseConfiguration對象
Configuration conf = HBaseConfiguration.create(); - 創建Connectiond對象
Connection connection = ConnectionFactory.createConnection(conf); - 注意Zookeeper集群的本地HOST配置
- 創建DDL操作對象Admin
Admin admin = connection.getAdmin() - 通過Admin對象的方法操作名稱空間、表
- 關閉資源
admin.close();
- API之DDL操作
- namespace
- 創建
- 查看
- 修改
- 刪除
- 抽取HBaseUtils
- table
- 創建
- 判斷表是否存在
- 刪除
- 總結:DDL通過HBaseAdmin操作名稱空間和表
- API之DML操作
- 注意:DML的操作對象不再是HBaseAdmin而是Table對象
Table table = connection.getTable(TableName.valueOf("ns1:t1")); - 添加記錄
- Table的put(Put put);
- 獲取數據
- get的基本使用
- get指定的Family和Qualifier
- 掃描數據
- scan的基本使用
- scan指定的Family和Qualifier
- scan範圍掃描
- 刪除數據
- 刪除行
- 刪除指定的Qualifier
5.2 API高級
- 過濾器
- 語法格式
scan '表名', { Filter => "過濾器(比較運算符, '比較器')" } - 查看過濾器的命令,能夠查到支持的所有過濾器:show_filters
- 行鍵過濾器
ta-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
過濾器名稱作用示例
- 列簇與列過濾器
ta-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
過濾器名稱作用示例
- 值過濾器
ta-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
過濾器名稱作用示例
- 其他過濾器
ta-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
過濾器名稱作用示例
- 比較器
e data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
六、HBase核心
6.1 架構分析
參考: HBase.ppt
- HBase客戶端
- Shell命令接口
- Java API編程接口
- Thrift/REST API編程接口
- MapReduce編程接口
- 緩存hbase:meta數據
- Zookeeper
- Zookeeper為HBase選舉 Master,避免單點HMaster單點故障問題,實現HMaster的高可用
- 存儲所有 Region 的尋址入口:hbase:meta表在哪臺服務器上。
- 實時監控 RegionServer 的狀態,將 RegionServer 的上線和下線信息實時通知給 Master
- 存儲 HBase 的 Schema,包括有哪些 Table,每個 Table 有哪些 Column Family
- Master
- 為任務量小的RegionServer分配Region,實現集群的負載均衡
- 維護集群中,表的元數據信息
- 發現失效的Region,指揮RegionServer將失效的Region分配到正常的RegionServer上
- 當RegionServer掛掉後,協調RegionServer將HLog進行拆分,分給剩餘正常的RegionServer,故障轉移
- RegionServer
- 管理Master分配的Region
- 處理來自Client的讀寫請求
- 和底層的HDFS交互,存儲數據Flush到HDFS中
- 負責Region變大之後的拆分
- 負責StoreFile的合併工作,防止小文件過多
- HRegion
- 數據表的行方向的切割分片,分佈在不用的Region Server。
- Region由一個或者多個Store組成,每個Store保存一個Column Family。
- 每個Region由以下信息標識:< 表名,StartRowkey,創建時間>
- Store
- 每一個Region由一個或多個Store組成,每個 ColumnFamily對應一個Store
- 一個Store由一個memStore和0或者 多個StoreFile組成
- HBase以store的大小來判斷是否需要切分region
- MemStore
- MemStore是一個內存級別的存儲,一個列族Store對應一個MemStore
- 當MemStore的大小達到一個閥值時,MemStore會被flush到文 件
- StoreFile
- StoreFile是磁盤級別存儲的文件組件
- Memstore內存中的數據寫到文件後就是StoreFile,StoreFile底層是以HFile的格式保存
- 當Storefile文件的數量增長到一定閾值後,系統會進行合併,
- 在合併過程中會進行版本合併和刪除工作,形成更大的Storefile
- HFile
- HFile是StoreFile的存儲格式,例如txt、orc等
- 查看HFile文件數據命令
hbase org.apache.hadoop.hbase.io.hfile.HFile -e -p -f 文件路徑
- WAL(HLog)
- 保證數據的高可靠性:HBase隨機寫入數據的時候,先寫入緩存,再異步刷新落盤,為了防止緩存數據丟失,數據寫入緩存之前需要首先順序寫入HLog
- HDFS
- 實際存儲數據的分佈式文件系統
- 數據默認3副本存儲策略有效保證數據的高可靠性
6.2 尋址機制
- 尋址步驟:
- 第 1 步:Client 請求 Zookeeper 獲取hbase:meta元數據表所在的 RegionServer 的地址。
- 第 2 步:Client 請求hbase:meta所在的 RegionServer 再次獲取訪問數據所在的 RegionServer 地址,Client 會將hbase:meta的相關信息 cache 下來,以便下一次快速訪問。
- Region的RowKey構成:表名,StartRowkey,創建時間.整體進行MD5 Hash值
- 第 3 步:Client 請求數據所在的 RegionServer,操作數據。
參考: HBase.ppt
6.3 寫入流程
- 寫流程
1、Client 先根據 RowKey 找到對應的 Region 所在的 RegionServer
2、Client 向 RegionServer 提交寫請求
3、RegionServer 找到目標 Region
4、Region 檢查數據是否與 Schema 一致
5、如果客戶端沒有指定版本,則獲取當前系統時間作為數據版本
6、將更新寫入 WAL Log
7、將更新寫入 MemStore
8、判斷 MemStore 的是否需要 flush 為 StoreFile 文件。 - 寫流程源碼查看
6.4 讀取流程
- 流程
1、客戶端通過 ZooKeeper 以及-ROOT-表和.META.表找到目標數據所在的 RegionServer(就是 數據所在的 Region 的主機地址)
2、聯繫 RegionServer 查詢目標數據
3、RegionServer 定位到目標數據所在的 Region,發出查詢請求
4、Region 先在 Memstore 中查找,命中則返回
5、如果在 MemStore 中找不到,則在 StoreFile 中掃描 為了能快速的判斷要查詢的數據在不在這個 StoreFile 中,應用了 BloomFilter
6.5 MemStore Flush
- 觸發條件
- MemStore級別限制:當Region中任意一個MemStore的大小達到了上線,會觸發MemStore刷新
hbase.hregion.memstore.flush.size 默認128M - Region級別限制:當Region中所有的MemStore的大小和總和達到了上線會觸發MemStore刷新
hbase.hregion.memstore.block.multiplier*hbase.hregion.memstore.flush.size - RegionServer級別限制:當RegionServer中MemStore的大小中和超過低水位閾值,RegionServer開始強制執行flush
hbase.regionserver.global.memstore.size.lower.limit*hbase.regionserver.global.memstore.size - 當一個RegionServer中HLog數量達到上線時,系統會選取最早的HLog對應的一個或多個Region進行flush
hbase.regionserver.maxlogs - HBase定期刷新MemStore:默認週期為1小時,確保MemStore不會長時間沒有持久化
- 手動執行flush:用戶可以通過shell命令flush 'tablename' 或者 flush 'regionname'分別對一個表或者一個Region進行flush
6.6 Compaction
Compaction是從一個Region的一個Store中選取部分HFile文件進行合併。
- Compacton分類
- Minor Compaction 是值選取部分小的、相鄰的HFile,將他們合併成一個更大的HFile。
- Major Compaction 是指將一個Store中所有的HFile合併成一個HFile,這個過程還會清理三類無意義的數據:被刪除的數據、TTL過期數據、版本號超過超過設定版本號的數據
- Compaction時機
- MemStore Flush:MemStore Flush會產生HFile文件,因此在每次執行完後,都會對當前Store中的文件數進行判斷,一旦Store中總文件數大於hbase.hstore.compactionThrshold,就會觸發Compaction。
- 後臺線程週期性檢查:RegionServer會在後臺啟動一個線程CompactionChecker,定期觸發檢查對應Store是否要執行Compaction。檢查週期算法
hbase.server.thread.wakefrequency*hbase.server.compactchecker.interval.multiplier - 手動觸發
6.7 Region Split
默認情況下,每個Table只有一個Region。隨著數據的不斷寫入,Region會自動進行拆分,拆分後的Region會被分配到其他RegionServer上,實現HBase的負載均衡。
- HBase已經有6種Split觸發策略,常見的Split策略如下:
- ConstantSizeRegionSplitPolicy:表式一個Region中最大Stroe的大小超過設置閾值(hbase.hregion.max.filesize)之後會觸發分裂。
- IncreasingToUpperBoundRegionSplitPolicy:一個Region中最大Store的大小超過設置閾值就會觸發分裂。但是這個閾值並不像ConstantSizeRegionSplitPolicy是一個固定的值,而是在一定條件下不斷調整,調整後的閾值大小和Region所屬表在當前RegionServer上的Region個數有關係,調整後的閾值等於(#regions)*(#regions)*(#regions)* flush size * 2,當然閾值並不會無線增大,最大值為用戶設置的MaxRegionFileSize。
- SteppingSplitPolicy:這種分裂閾值也發生了變化,相比第二種方式簡單了一些,分裂閾值大小和待分裂Region所屬表在當前RegionServer上的Region個數有關係,如果Region個數等於1,分裂閾值為 flush size * 2,否則為MaxRegionFileSize。
- Pre Split
如果知道hbase數據表的key的分佈情況,就可以在建表的時候對hbase進行region的預分區。這樣做的好處是防止大數據量插入的熱點問題,提高數據插入的效率。 - 預切割命令
create 'ns1:tb1',{NAME => 'f1'},{NAME => 'f2'},SPLITS => ['01','02','03']
- 表預切割案例
6.8 版本
- 版本設置
HBase中的表,支持十億行 * 百萬列 * 千版本 - 創建表的時候,需要給列簇指定版本,並且只能給列簇指定版本。
create 'ecitem:Beans', {NAME => 'f1', VERSIONS => 3} - 查詢指定版本數的數據
# 返回兩個版本的數據,不指定版本返回一個最新版本
get 'ecitem:Beans','row001',{COLUMN=>'f1:name',VERSIONS=>2} - 指定時間戳精確查詢
get 'ecitem:Beans','row001',{COLUMN =>'f1:name',TIMESTAMP=>1543325344120} - 指定時間戳範圍查詢
get 'ecitem:Beans','row001',{COLUMN => 'f1:name',TIMERANGE=>[1543325325769,1543325344120]}
- TTL
TTL是作用於列族的,它設置了一個基於時間戳的臨界值, 內部的管理會自動檢查TTL值是否達到上限,在major合併過程中時間戳被判定為超過TTL的數據會被自動刪除。
TTL參數的單位是秒,默認值是Integer.MAX_VALUE,即2^31-1=2 147 483 647 秒,大約68年。使用TTL默認值的數據可以理解為永久保存。 - 建表的時候指定TTL,默認值為'FOREVER',永不過期
create 't_task_log',{NAME => 'f', TTL=>'86400'} - 原生掃描:顯示包括刪除的數據
scan 'table',{RAW=>true,VERSIONS=>10} - TTL&MIN_VERSION
- 即使超過TTL設置,依然要保留最小版本數相應的版本個數
- KEEP_DELETE_CELL
- 當值為false,刪除列數據,執行flush ,Scan RAW發現delete標籤數據存在,magor_complet後delete標籤數據不存在。
- 當值為true,刪除列數據,執行flush,Scan RAW發現delete標籤數據存在,magor_complet後delete標籤數據存在。
七、HBase高級
7.1 計數器
HBase也有一種機制可以將列當作計數器。否則,如果用戶需要對一行數據加鎖,然後讀取數據,再對當前數據做加法,最後寫回 HBase並釋放該行鎖,從而其他寫程序可以訪問該行數據。這樣做會引起大量的資源競爭問題,尤其是當客戶端進程崩潰之後,尚未釋放的鎖需要等待超時恢復——這會在一個高負載的系統中引起災難性的後果。
計數器是面向列的操作,即每次對特定計數器的操作只會鎖住一列而不是一行,然後讀取數據,再對當前數據做加法操作,最後再寫入HBase中並釋放該列的鎖,在操作的過程中用戶是可以訪問這一行的其他數據的
解決SQL中:update student set age = age + 1 where id = 1;
- 計數器命令
incr '','','',[increment-value>]- 增加值和對計數器產生的作用:
ble data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">
- 單計數器
單計數器顧名思義就是一次操作只能操作一個計數器,用戶需要自己設置列,方法由HTable類提供 - 多計數器
單計數器每一次只允許操作一個計數器,如果一行中多個列都是計數器則需要將代碼重複編寫,因此HBase的HTable類提供了另外一個方法,可以一次操作同一行的多個計數器
7.2 BloomFilter
- BloomFilter的作用
HBase利用BloomFilter來提高隨機讀(Get)的性能,對於順序(Scan)而言,設置Bloomfilter是沒有作用的(0.92以後,如果設置了bloomfilter為ROWCOL,對於指定了qualiter的Scan有一定的優化)。 - BloomFilter在HBase中的開銷
BloomFilter是一個列族級別的配置屬性,如果在表中設置了BloomFilter,那麼HBase會在生成StoreFile時,包含一份BloomFilter 結構的數據,稱其為MetaBlock;MetaBlock與DataBlock(真實的KeyValue數據)一起由LRUBlockCache維護,所以開啟BloomFilter會有一定的存儲及內存cache開銷。 - BloomFilter的類型
- ROW:根據KeyValue中的row來過濾storefile。
- ROWCOL:根據KeyValue中的row+qualifier來過濾storefile。
- 總結
- 任何類型的get(基於rowkey或row+col)Bloom Filter的優化都能生效,關鍵是get的類型要匹配Bloom Filter的類型
- 基於row的scan是沒辦法走Bloom Filter的。因為Bloom Filter是需要事先知道過濾項的。對於順序scan是沒有事先辦法知道rowkey的。而get是指明瞭rowkey所以可以用Bloom Filter,scan指明column同理。
- row+col+qualify的scan可以去掉不存在此qualify的storefile,也算是不錯的優化了,而且指明qualify也能減少流量,因此scan儘量指明qualify
7.3 RowKey設計
- RowKey設計原則
- 長度原則
- Rowkey 是一個二進制碼流,Rowkey 的長度被很多開發者建議說設計在 10~100 個字節,不過建議是越短越好,不要超過 16 個字節,存為byte[]字節數組,一般設計成定長的。
- 原因如下:
- 數據的持久化文件 HFile 中是按照 KeyValue 存儲的,如果 Rowkey 過長比如 100 個字 節,1000 萬列數據光 Rowkey 就要佔用 100*1000 萬=10 億個字節,將近 1G 數據,這會極大 影響 HFile 的存儲效率;
- MemStore 將緩存部分數據到內存,如果 Rowkey 字段過長內存的有效利用率會降低, 系統將無法緩存更多的數據,這會降低檢索效率。因此 Rowkey 的字節長度越短越好。
- 目前操作系統是都是 64 位系統,內存 8 字節對齊。控制在 16 個字節,8 字節的整數 倍利用操作系統的最佳特性。
- 散列原則
- 如果 Rowkey 是按時間戳的方式遞增,不要將時間放在二進制碼的前面,建議將 Rowkey 的高位作為散列字段,由程序循環生成,低位放時間字段,這樣將提高數據均衡分佈在每個 Regionserver 實現負載均衡的幾率。如果沒有散列字段,首字段直接是時間信息將產生所有 新數據都在一個 RegionServer 上堆積的熱點現象,這樣在做數據檢索的時候負載將會集中 在個別 RegionServer,降低查詢效率。
- 唯一原則
- 必須在設計上保證其唯一性。rowkey 是按照字典順序排序存儲的,因此,設計 rowkey 的時候,要充分利用這個排序的特點,將經常讀取的數據存儲到一塊,將最近可能會被訪問 的數據放到一塊。
- 解決熱點問題
- 加鹽
- HASH
- 反轉
- 時間戳反轉
八、備份與恢復
8.1 Snapshot
- 什麼是Snapshot
HBase 從0.95開始引入了Snapshot,可以對table進行Snapshot,也可以Restore到Snapshot。Snapshot可以在線做,也可以離線做。Snapshot的實現不涉及到table實際數據的拷貝,僅僅拷貝一些元數據,比如組成table的region info,表的descriptor,還有表對應的HFile的文件的引用。
8.2 相關命令
<code># 建立快照: snapshot 'tableName', 'snapshotName' # 列出快照: list_snapshots # 刪除快照 delete_snapshot 'snapshotName' # 從快照複製生成一個新表 clone_snapshot 'snapshotName', 'newTableName' # 用快照恢復數據,它需要先禁用表,再進行恢復 disable 'tableName' restore_snapshot 'snapshotName'/<code>
九、HBase調優
9.1 讀性能調優
9.2 寫性能調優
十、高級應用
10.1 MR操作HBase
- HBase作為MR的數據源,實現聚合操作
- 使用HBase的SnapShot獲取相應的HFile文件地址,MR操作HFile文件
10.2 Hive結合HBase
- HBase作為Hive的外表,實現離線分析
收藏
舉報
黑馬程序員Loading...掃碼下載今日頭條
關鍵字: 版本 RegionServer 讀寫