HBase
HBase介紹
簡介
- 是一個高可靠性、高性能、面向列、可伸縮、實時讀寫的分布式資料庫
- 利用Hadoop HDFS作為其檔案存盤系統
- 利用Zookeeper作為其分布式協同服務主要用來存盤非結構化和半結構化的松散資料(列存 NoSQL 資料庫)
優點
-
容量大
- 單表可以有百億行、百萬列
-
面向列
- 資料在表中是按照某列存盤的,這樣在查詢只需要少數幾個欄位的時候,能大大減少讀取的數量
-
多版本
- 每一個列的資料存盤有多個Version
-
稀疏性
- 為空的列并不占用存盤空間,表可以設計的非常稀疏
-
拓展性
- 底層依賴HDFS,當磁盤空間不足的時候,只需要動態增加datanode節點服務(機器)就可以了
-
高可靠性
- WAL機制,保證資料寫入的時候不會因為集群例外而導致寫入資料丟失
- Replication機制,保證了在集群出現嚴重的問題時候,資料不會發生丟失或者損壞
- Hbase底層使用HDFS,本身也有備份
-
高性能
- 底層的LSM資料結構和RowKey有序排列等架構上的獨特設計,使得Hbase寫入性能非常高
應用
-
資料庫量要足夠多
-
保證硬體資源足夠
-
內部應用
- 存盤業務資料
- 存盤日志資料
- 存盤業務附件
HBase資料模型
命名空間
NameSpace
資料庫
-
命名空間是類似于關系資料庫系統中的資料庫的概念,他其實是表的邏輯分組
-
命名空間是可以管理維護的,可以創建,洗掉或更改命名空間
-
HBase有兩個特殊預定義的命名空間
- default - 沒有明確指定名稱空間的表將自動落入此名稱空間
- hbase - 系統命名空間,用于包含HBase內部表
表
Table
表
- 存盤相同資料的一個邏輯單元
- 表有多個行資料組成,行有很多列組成
- HBase是一個半結構的資料庫, 所以每行的列都有可能是不同
RowKey
主鍵
- 可以理解為一行資料的主鍵
- Hbase按照列進行存盤,所以我們查詢資料的時候會看到很多RowKey相同的列
- 多可以有64K位元組組成股能10-40個位元組即可
- 將來設計RowKey是Hbase使用的重中之重
- RowKey存盤的時候默認以字典序排序
列簇
Column Family
列
- 可以理解為多個列的集合
- 方便佇列進行查找和管理
- 一個表的列族需要使用之前宣告(創建表、后期維護表)
- 列隸屬于列族,列族隸屬于表
- 一個表中列族是固定的但列不是固定的
列
Column Qualifier
- 個列族中的列是不固定的
- 有可能有的資料行一個列族中有3個列,有的行相同列族有8個列
- 使用的時候必須列族:列
資料版本
Timestamp
- 默認就是時間戳,解決HDFS不能隨時修改資料的弊端
- 默認資料版本就是時間戳
- 查詢資料的時候默認顯示最新的資料
資料
Cell
- row, column family,column qualifier,version
- 所有的資料都是字串
HBase訪問方式
HBase shell
-
Shell實作DDL操作
-
創建一個表
-
create ‘t1’,{NAME => ‘f1’, VERSIONS => 2},{NAME => ‘f2’, VERSIONS => 2}
-
標準創建
- create ‘member’,‘member_id’,‘address’,‘info’
-
-
獲得表的描述
- describe
-
洗掉一個列族,alter,disable,enable
-
alter ‘member’,{NAME=>‘member_id’,METHOD=>‘delete’}
-
將表enable
- enable ‘member’
-
列出所有的表
- list
-
drop一個表
- create ‘temp_table’,‘member_id’,‘address’,‘info’
- hbase(main):029:0>disable ‘temp_table’
- hbase(main):030:0>drop ‘temp_table’
-
-
查詢表是否存在
- hbase(main):021:0>exists ‘member’
-
-
Shell實作DML操作
-
插入、更新
- put’member’,‘guojing’,‘info:age’,‘24’
-
洗掉id為temp的值的‘info:age’欄位
- delete ‘member’,‘temp’,‘info:age’
-
洗掉整行
- deleteall ‘member’,‘xiaofeng’
-
查詢表中有多少行
- count ‘member’
-
給‘xiaofeng’這個id增加’info:age’欄位,并使用counter實作遞增
- incr ‘member’,‘xiaofeng’,‘info:age’
-
獲取當前count的值
- get_counter ‘member’,‘xiaofeng’,‘info:age’
-
將整張表清空
- truncate ‘member’
-
使用count命令計算表的行數量
- count ‘member’
-
-
Shell實作DQL操作
-
獲取一個id的所有資料
- get ‘member’,‘linghuchong’
-
獲取一個id,一個列族的所有資料
- get ‘member’,‘linghuchong’,‘info’
-
獲取一個id,一個列族中一個列的所有資料
- get ‘member’,‘linghuchong’,‘info:age’
-
通過timestamp來獲取兩個版本的資料
- get ‘member’,‘linghuchong’,
{COLUMN=>‘info:age’,TIMESTAMP=>1321586238965} - get ‘member’,‘linghuchong’,
{COLUMN=>‘info:age’,TIMESTAMP=>1321586571843}
- get ‘member’,‘linghuchong’,
-
全表掃描
- scan ‘member’
- 一般都和過濾器一起使用
-
-
Shell實作Region管理
-
移動region
- move ‘encodeRegionName’, ‘ServerName’
-
開啟/關閉region
- balance_switch true|false
-
手動split
- split ‘regionName’, ‘splitKey’
- 洗掉之后當前Region并不會馬上消失,需要等待HBase檢查新Region的作業狀態
-
手動觸發major compaction
- major_compact ‘t1’
-
-
總結
-
通用命令
- status: 提供HBase的狀態,例如,服務器的數量,
- version: 提供正在使用HBase版本,
- table_help: 表參考命令提供幫助,
- whoami: 提供有關用戶的資訊,
-
資料操縱語言
- put: 把指定列在指定的行中單元格的值在一個特定的表,
- get: 取行或單元格的內容,
- delete: 洗掉表中的單元格值,
- deleteall: 洗掉給定行的所有單元格,
- scan: 掃描并回傳表資料,
- count: 計數并回傳表中的行的數目,
- truncate: 禁用,洗掉和重新創建一個指定的表,
-
資料定義語言
-
create: 創建一個表,
-
list: 列出HBase的所有表,
-
disable: 禁用表,
- 要洗掉表或改變其設定,首先需要使用 disable 命令關閉表,使用 enable 命令,可以重新啟用它,
-
-
HBase架構模型
Client
- HBase的客戶端,可以向HBase服務器發送請求
- 既可以是shell,也可以是Api
- 操作包括DDL DML DQL ,HBase不支持多表關聯查詢
- 客戶端必要的時候會對資料進行一些快取
HMaster
- HBase的主節點
- 責接收客戶端的請求(僅限于DDL)
- 主(有負載均衡,單點故障)
- HMaster也可以實作高可用(active–standby)
- 主備的切換由Zookeeper負責監督維護
- 但是HMaster沒有聯邦機制,業務承載能力還是有限的
- 一個資料庫的表的結構很少會發生變化,但是絕大部分是CRUD操作
- 于是HBase的Master只負責DDL,DMLDQL由其他節點承擔
- 負責管理HRegionServer的健康狀況
- 上下線的監督----創建表的時候分配Region
HRegionServer
- HBase的具體作業節點,一般一臺主機就是一個Region
- 一個RegionServer中包含很多的Region,HMaster負責分配Region
- 負責接收客戶端的DML和DQL請求,建立連接???
HRegion
- HBase的表資料具體存放的位置
- 一個Region只隸屬于一張表,但是一張表可以有多個Region
- 一個Region只隸屬于一張表,但是一張表可以有多個Region
Store
-
一個表中一個列簇對應一個Store
-
一個Store里面分為1個MemStore和N個StoreFile
-
MemStore
- 資料最開始優先寫入到MemStore當Flush的時候才會被寫入到磁盤
- 默認情況下一個MemStore的大小為128M
- 當客戶端向資料庫插入資料的時候,當記憶體使用到128M的時候
- 直接重新申請128M的記憶體空間,資料直接寫到新記憶體中,原來已經滿的資料寫出到HDFS,稱為HFile
-
Storefile
- 資料存盤檔案的映射,對應HDFS上的HFlle
- 一個Table對應多個Region,一個Region對應多個Store,一個Store對應一個MemStore和多個StoreFlle
- 多個StoreFile內部有序,但是外部無序
- 集群會設定一些閾值,當達到閾值的時候開始將小檔案合并成大檔案
-
-
MemStore:基于記憶體存放資料,每個Store大概分配128M的空間
-
StoreFile:是檔案的硬碟存盤,直接存盤到HDFS,存到HDFS之后被稱之為HFile
Hlog
- HBase的日志機制(WAL)
- 日志也會存盤到HDFS,在任何操作之前先記錄日志到HDFS
- 以后MemStore丟失資料或者RegionServer例外都能夠通過日志進行恢復
- 一個RegionServer對應一個HLog
zookeeper
- HBase協調服務
- 1.主備的選舉與切換
- ⒉.記錄當前集群的狀態資訊,當主備切換的時候集群的狀態可以被新主節點直接讀取到
- 3.記錄當前集群的資料存放資訊
- 4.存盤Hbase的元資料資訊
HBase讀寫流程
公共流程(三層索引)
-
HBase 0.96以前
- 首先系統維護了兩張表-root-.meta.
- .meta.表中存盤了表對應Region對應的RegionServer RowKey的區間
- 但是.meta.表也是一張普通的Hbase表,也需要存放到RegionServer
- 于是專門使用-root-表來記錄.meta.的存放位置
- 認為ROOT表只需要一個Region即可,-ROOT-的Region資訊就被記錄到Zookeeper
-
HBase 0.96以后
- -ROOT-表被移除,直接將.Meta表region位置資訊存放在Zookeeper中
- Meta表更名為hbase:meta
讀取資料流程
寫入資料流程
資料刷寫(Memstore Flush)
觸發時機
-
Region 中所有 MemStore 占用的記憶體超過相關閾值
-
整個 RegionServer 的 MemStore 占用記憶體總和大于相關閾值
-
WAL數量大于相關閾值
-
定期自動刷寫
-
資料更新超過一定閾值
-
手動觸發刷寫
-
特別注意
- 以上所有條件觸發的刷寫操作最后都會檢查對應的 HStore 包含的 StoreFiles 檔案數是否超過hbase.hstore.blockingStoreFiles 引數配置的個數,默認值是16,
- 如果滿足這個條件,那么當前刷寫會被推遲到hbase.hstore.blockingWaitTime 引數設定的時間后再刷寫,
- 在阻塞刷寫的同時,HBase 還會請求 Compaction 或者Split 操作,
刷寫策略
-
HBASE1.1之前
- MemStore 刷寫是 Region 級別的,就是說,如果要刷寫某個 MemStore ,MemStore 所在的 Region 中其他 MemStore 也是會被一起刷寫的
-
HBASE2.x之后
-
FlushAllStoresPolicy
- 每次刷寫都是對 Region 里面所有的 MemStore 進行的
-
FlushAllLargeStoresPolicy
- 判斷 Region 中每個 MemStore 的使用記憶體是否大于某個閥值,大于這個閥值的MemStore 將會被刷寫,
- flushSizeLowerBound = max((long)128 / 3, 16) = 42
-
FlushNonSloppyStoresFirstPolicy
-
刷寫流程
-
prepareFlush 階段
- 如果MEM要進行刷寫
- 對記憶體中的資料拍攝快照,拍攝時間會非常短
- 拍攝期間記憶體中的資料會被鎖定,保證快照期間資料的安全
-
flushCache 階段
- 將快照的資料寫成一個臨時檔案到硬碟
- 將臨時檔案更名稱正式檔案存盤到對應的列簇中
資料合并(Compaction)
合并分類
-
Minor Compaction(小型)
- 選取一些小的、相鄰的StoreFile將他們合并成一個更大的StoreFile
- 僅僅是合并不會處理被洗掉的或者失效的資料
- 但是會處理超過TTL的資料
- 一次Minor Compaction的結果是讓小的storefile變的更少并且產生更大的StoreFile,
-
Major Compaction(大型)
- 將所有的StoreFile合并成一個StoreFile
- 清理三類無意義資料:被洗掉的資料、TTL過期資料、版本號超過設定版本號的資料,
- 但是對整個集群影響較大,一般手動合并
合并時機
- Memstore刷盤
- 周期性檢查
- 手動觸發
合并策略
-
執行緒池選擇
-
合并策略選擇
- minor 策略: RatioBasedCompactionPolicy (0.96.x之前)
- ExploringCompactionPolicy(當前默認)
資料切分(Region Split)
切分原因
- 最開始—個表只有—個Region
- 對于這個表的查詢都會被定位到這一個RegionServer
- 當Region達到閾值的時候就會進行切分
- 單點壓力讀寫性能合并困難
觸發時機
-
每次資料合并之后,發起個requestSplit
然后開始檢查檔案的大小是否達到閾值-
ConstantSizeRegionSplitPolicy
- 10G
-
lncreasingToUpperBound
- 256M ----2048M —.,, ,—10G
-
切分流程
-
尋找切分點
- 先找最大的Store.然后再找最大的StoreFile,再找到中心點位置的RowKey
-
切分
Hbase表設計要點
行健設計
-
注意
- 行健不能改變,唯一可以改變的方式是先洗掉后插入
-
長度原則
- 語短越好
- Rowkey 是一個二進制碼流,最大長度是64KB,建議越短越好,10-100長度即可,不要超過 16 個位元組
-
散列原則
- 盡量將連續的資料存放到更多的RegionServer
-
唯一原則
- 必須在設計上保證其唯一性,rowkey 是按照字典順序排序存盤的
- 設計 rowkey 的時候,要充分利用這個排序的特點,將經常讀取的資料存盤到一塊,將最近可能會被訪問 的資料放到一塊
-
資料熱點
-
原因
- 熱點發生在大量的 client 直接訪問集群的一個或極少數個節點
- 大量訪問會使熱點region所在的單個機器超出自身承受能力,性能下降甚至 region 不可用
-
策略
-
RowKey反轉策略
- 例:x01、x02、x03存放在同一節點
反轉x10、x20、x30就會存放在不同的節點
- 例:x01、x02、x03存放在同一節點
-
加鹽策略
- 在 rowkey 的前面增加亂數
-
哈希策略
- 哈希會使同一行永遠用一個前綴加鹽,哈希也可以使負載分散到整個集群,但是讀卻是可以預測的
-
-
列簇設計
- 追求的原則是:在合理范圍內能盡量少的減少列簇就盡量減少列簇
- 列簇的名字盡可能短,優先使用首字母
HBase設計案例
單表RowKey設計
-
移動通話記錄
-
手機號碼_時間
-
首先按照手機號碼排序,手機號相同的會排在一起
-
然后按照時間排序,會按照時間先后順序排序
-
180-20201018102345678
- 180-20201001
- 180-20201101
-
-
京東訂單
-
RowKey
- uname_timestramp 將相同用戶的訂單全部排列到一起,查詢的時候只是從里面取出一小部分
-
列族
- order
-
列
- datetime、orderid、usernamegoodimgs、title、number、money
-
versions
- 1
-
多表關聯RowKey設計
-
人員職位映射表
-
規則
- 一個人可以有多個身份
- 一個身份可以被多個人擁有
- 一個人可以指定他的主要身份
-
要求
- 通過這個人的ID可以獲取身份
- 通過身份可以獲取個人
- 可以修改人的身份
- 可以修改身份對應的人員
- 人員可以設定主身份
-
方案
-
構建一個列族,將和自己關聯到一起的資料全部以列名的方式存放
-
身份表
-
人員表
-
-
-
微博關系處理
- 人員表(rowkey,列族(個人資訊,安全,統計資訊(關注數,被關注數,發帖數)))
- 關注表(rowkey,列族(關注:rowkey))
- 粉絲表(rowkey,列族(被關注:rowkey))
- 發帖表(人員rowkey_timestamp)
HBase常用優化
HBase表優化
-
預磁區 Pre-Creating Regions
- 默認情況下,在創建HBase表的時候會自動創建一個region磁區,當匯入資料的時候,所有的HBase客戶端都向這一個region寫資料,直到這個region足夠大了才進行切分,
- 有種加快批量寫入速度的方法是通過預先創建一些空的regions,這樣當資料寫入HBase時,會按照region磁區情況,在集群內做資料的負載均衡,
-
rowkey
-
設計row key時,將經常一起讀取的資料存盤到一塊,將最近可能會被訪問的資料放在一塊
-
Rowkey規則
- 1、 越小越好
- 2、 Rowkey的設計是要根據實際業務來
- 3、定長
- 3、 散列性
- a) 取反 001 002 100 200
- b) Hash
- c) 加鹽
-
-
ColumnFamily
- 不要在一張表里定義太多的column family
- Hbase并不能很好的處理超過2~3個columnfamily的表
- 某個column family在flush的時候,它鄰近的column family也會因關聯效應被觸發flush,最終導致系統產生更多的I/O
-
Version
- 創建表的時候設定表中資料的最大版本
- 創建表的時候設定表中資料的存盤生命期,過期資料將自動被洗掉
-
compact & Split
HBase寫入優化
-
多Table并發寫
- 創建多個Table客戶端用于寫操作,提高寫資料的吞吐量
-
WAL Flag
- 首先會先寫WAL(WriteAhead Log)日志(即HLog,一個RegionServer上的所有Region共享一個HLog),只有當WAL日志寫成功后,再接著寫MemStore
- 因此,對于相對不太重要的資料,可以在Put/Delete操作時,通過呼叫Put.setWriteToWAL(false)或Delete.setWriteToWAL(false)函式,放棄寫WAL日志,從而提高資料寫入的性能
-
批量寫
- 批量寫入多行記錄,這樣做的好處是批量執行,只需要一次網路I/O開銷
HBase讀取優化
-
顯示的指定列
- 當使用Scan或者GET獲取大量的行時,最好指定所需要的列
-
關閉ResultScanner
- 如果在使用table.getScanner之后,忘記關閉該類,它會一直和服務端保持連接,資源無法釋放,從而導致服務端的某些資源不可用
-
查詢結果
- 對于頻繁查詢HBase的應用場景,可以考慮在應用程式和Hbase之間做一層快取系統,新的查詢先去快取查,快取沒有再去查Hbase
HBase快取優化
-
設定Scan快取
- 可以有效的減少服務端與客戶端的互動
-
禁用塊快取
- 批量進行全表掃描,默認是有快取的,如果此時有快取,會降低掃描的效率
- 對于經常讀到的資料,建議使用默認值,開啟塊快取
-
快取查詢結果
- 對于頻繁查詢HBase的應用場景,可以考慮在應用程式和Hbase之間做一層快取系統,新的查詢先去快取查,快取沒有再去查Hbase
HBase和MapReduce整合
公共代碼
Hdfs資料存入Hbase
HBase檔案匯出Hdfs
Hive和HBase的整合
Hive提供了與HBase的集成,使得能夠在HBase表上使用HQL陳述句進行查詢 插入操作以及進行Join和Union等復雜查詢、同時也可以將hive表中的資料映射到Hbase中
Protobuf資料壓縮
簡介
- protocol buffers 是一種語言無關、平臺無關、可擴展的序列化結構資料的方法
使用流程
- 先撰寫protobuf語言代碼,設定壓縮的欄位和范圍
- 執行bin下的proto程式,將protobuf的程式編譯為java程式
- 使用hbaseapi的時候(加載或者讀取),使用protobuf里邊的方法
Protobuf 的優點
- Protobuf 有如 XML,不過它更小、更快、也更簡單
- 你可以定義自己的資料結構,然后使用代碼生成器生成的代碼來讀寫這個資料結構
Protobuf 的不足
- 功能簡單,無法用來表示復雜的概念
- Protobuf 只是 Google 公司內部使用的工具,在通用性上還差很多
Phoenix
簡介
- Phoenix是構建在HBase上的一個SQL層,能讓我們用標準的JDBC APIs而不是HBase客戶端APIs來創建表,插入資料和對HBase資料進行查詢
Phoenix系統架構
-
重客戶端架構
-
客戶端包括應用程式開發,將SQL進行決議優化生成QueryPlan,進而轉化為HBase Scans,呼叫HBase API下發查詢計算請求,并接識訓傳結果;
-
服務端主要是利用HBase的協處理器(Phoenix-core包里面包含hbase-client,以及hbase-server包),處理二級索引、聚合及JOIN計算等
-
缺陷
- 需要引入Phoenix內核依賴,目前一個單獨Phoenix重客戶端集成包已達120多M
- 運維不便,Phoenix仍在不斷優化和發展,一旦Phoenix版本更新,那么應用程式也需要對應升級版本并重新發布
- 僅支持Java API,其他語言開發者不能使用Phoenix
-
-
輕客戶端架構
-
瘦客戶端是用戶最小依賴的JDBC驅動程式,與Phoenix依賴進行解耦,支持Java、Python、Go等多種語言客戶端;
-
QueryServer是一個單獨部署的HTTP服務,接收輕客戶端的RPC請求,并將SQL轉發給PhoenixCore進行決議優化執行;
- 類似hive的beeline
-
Phoenix Server與重客戶端架構相同
-
Phoenix資料模型
phoenix常用命令
-
查看所有表
- !tables
-
創建schema
- create schema school;
-
創建表
-
建完表后hbase中也會自動創建對應的表
#創建完的表名和欄位名都會自動轉成大寫,如需小寫,需在建表時給表名和欄位名前后加雙引號,如下:
create table school.teacher(
tno INTEGER NOT NULL PRIMARY KEY,
tname VARCHAR,
age INTEGER
);
-
-
插入/更新資料
- upsert into school.teacher (tno,tname,age) values(1,‘zhangsan’,23);
-
查詢插入的資料
- select * from school.teacher;
-
洗掉資料
- delete from school.teacher where id =1;
-
洗掉表
- drop table school.teacher;
-
洗掉schema
- drop schema school;
-
退出
- !quit
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/379495.html
標籤:其他
