09 HBase
1 HBase简介
1.1 定义
HBase是一种分布式、可扩展、支持海量数据存储的NoSql数据库。
1.2 数据模型
与关系型数据库类似
存储再一张表中,有行有列
底层物理存储结构(K-V),更像是一个multi-dimensional map(多维映射)。
1.2.1 逻辑结构
1.2.2 物理存储结构
1.2.3 数据模型
(1) Name Space
● 命名空间,类似于关系型数据库 database 的概念。
● 自带命令空间
● hbase — HBase内置的表
● default — 用户默认使用的命令空间
(2) Table
● 类似于关系型数据库的表概念
● 定义表时,只需要声明列族,写入数据时字段可以动态、按需指定。
(3) Row
● 表中每行数据由一个RowKey和多个Column(列)组成。
● 数据按照RowKey的字典顺序存储。
(4) Column
● 表中每列由Column Family(列族)和Column Qualifier(列限定符)进行限定。
● 例如 info:name info:age
● 建表时,只需指明列族,列限定符无需预先定义
(5) Time Stamp
● 用于标识数据的不同版本(version),值为写入HBase的事件。
(6) Cell
● 由 { rowkey,column Family:column Qulifier,time Stamp } 唯一确定的单元
● cell中的数据全部是字节码形式存贮。
1.3 基本架构
架构角色
Master(table+Region Server)——>Region Server(date+Region)——> Region
(1) Region Server
● 是Region的管理者,其实现类为HRegionServer
操作对象 | 方式 |
数据 | get、put、detele |
Region | splitRegion、compactRegion |
(2) Master
● 是Region Server的管理者,其实现类为HMaster
操作对象 | 方式 |
表 | create、delete、 |
Region Server | 分配Region到RegionServer中,监控RegionServer的状态,均衡负载和故障转移 |
(3) Zookeeper
HBase通过Zookeeper来实现
● Master的高可用
● RegionServer的监控
● 元数据的入口
● 集群配置的维护工作
(4) HDFS
为HBase提供最终的底层数据存储服务、提供高可用的支持。
2 HBase快速入门
2.1 HBase安装部署
2.2 HBase Shell操作
2.2.1 基本操作
命令 | 说明 |
bin/hbase sehll | 进入HBase客户端名命令行 |
help | 查看帮助命令 |
2.2.2 namespace相关命令
命令 | 说明 | 示例 |
List_namespace | 查看list_namespace有哪些namespace | list_namespace |
create_namespace | 创建命令空间 | create_namespace "test01",{"author"=>'yezi', "create_time"=>"2021-11-11"} |
describe_namespace | 查看命令空间详情 | describe_namespace 'test01' |
alter_namespace | 修改namespace信息(添加、修改属性) | alter_namespace "test01", {METHOD => 'unset', NAME =>'author' },{METHOD => 'set', 'create_time' => '2021-12-31'} |
drop_namespace | 删除指定的namespace | drop_namespace 'test01'; |
注意
● 添加/修改属性:alter_namespace 'ns1', {METHOD => 'set', 'PROPERTY_NAME' => 'PROPERTY_VALUE'}
● 删除属性:alter_namespace 'ns1', {METHOD => 'unset', NAME => ' PROPERTY_NAME '}
● 要删除的namespace必须是空的,其下没有表
2.2.3 DDL相关命令
命令 | 说明 | 示例 |
List | 列出hbase中所有的用户表 | list |
create | 创建表的关键字 | create 'student', 'info' |
describe | 查看表结构 | describe 'student' |
alter | 将列族info的VERSIONS改为5 | alter 'student', {NAME=>'info', VERSIONS=>5} |
为表student增加一个example列族 | alter 'student', NAME=>'example', VERSIONS=>3 | |
删除表student的example列族 | alter 'student', 'delete' => 'example' | |
disable | 使指定表为disable状态 | disable 'student' |
drop | 删除表 | deop 'student' |
2.2.4 DML相关命令
命令 | 说明 | 示例 |
put | 插入数据到表/更新指定字段的值 | put 'student', '1011', 'info:name', 'zhangsan' |
scan | 扫描查看表数据(全表) | scan 'student' |
扫描指定的列 | scan 'student', {COLUMNS=>'info:age'} | |
扫描多列,从rowkey为1001开始,取两条 | scan 'student', { COLUMNS=>['info:age','info:sex'],LIMIT=>2,STARTROW=>'1001' } | |
扫描全表,包括删除的版本 | scan 'student' ,{RAW=>true, VERSIONS=>5} | |
get | 查看指定“行”或“列族:列”的数据 | get 'student','1001' / get 'student','1001','info:name' |
count | 统计表数据行数 | count 'student' |
deleteall | 删除某rowkey的全部数据 | deleteall 'student', '1001' |
删除某额rowkey的某一列数据 | deleteall 'student', '1002', 'info:sex' | |
truncate | 清空表数据 | truncate 'student' |
3 HBase进阶
3.1 RegionServer架构
所有MenStore加起来的大小不能超过RegionServer上JVM内存的40%
(1) StoreFile
● 存储文件,保存实际数据的物理文件,其以Hfile的形式存储在HDFS上。
● 每个Store会有一个或多个StoreFile(HFile),数据在StoreFile中有序。
(2) MenStore
● 写缓冲
● 数据先存储在MenStore中 —— (根据rowkey进行字典排序)排序后 —— 等待刷写时机 —— 刷写到HFile
● 每次刷写都会形成一个新的HFile
● 最多滚动32个
(3) WAL
● 在MenStore排序后刷写到HFile之前,数据会先写在一个叫做Write-Ahead logfile的文件中
● 然后再写入MenStore中
● 所以在系统出现故障时,数据可以通过这个日志文件重建
(4) BlockCache
● 读缓存,每次查询出的数据会缓存在BlockCache中,方便下次查询。(冷数据,查询次数少的数据优先删除)
3.2 写流程
(1) Client先访问zookeeper,获取hbase:meta表位于哪个Region Server。
(2) 访问对应的Region Server,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个Region Server中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache,方便下次访问。
(3) 与目标Region Server进行通讯;
(4) 将数据顺序写入(追加)到WAL;
(5) 将数据写入对应的MemStore,数据会在MemStore进行排序;
(6) 向客户端发送ack;
(7) 等达到MemStore的刷写时机后,将数据刷写到HFile。
3.3 MemStore Flush
(1) 从单个memstore的角度
(2) 从regionserver的角度
(3) 从时间角度
(4) 从WAL预写日志角度考虑
3.4 读流程
1) 整体流程
(1)
(2)
(3)
(4)
(5)
(6)
2) Merge细节
3.5 StoreFile Compaction
1) 存在的问题
2) StoreFile Compaction的介绍
3.6 Region Split
1) 概念介绍
2) Region Split时机
4 HBase API
5 HBase优化
5.1 预分区
1)预分区概述
● HBase表创建时,只有一个分区(Region),当Region>10G,会被RegionServer进行Split分裂成两个分区。
● 频繁分区会严重影响HBase的性能。
● 每一个Region维护着startRow与endRow,依照原则提前分区,可提高HBase性能。
● 用户可以在创建表的时候,对表按照一定的规则分区。
2)设置预分区
手动设置分区 | 方法 |
①生成给定了数组数值范围预分区 | create 'staff1','info',SPLITS => ['1','2','3'] |
②生成16进制序列预分区 | create 'staff2','info',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'} |
②按照文件中设置的规则预分区 | create 'staff3','info',SPLITS_FILE => 'splits.txt' |
④使用Java API创建预分区 |
5.2 RowKey设计
1)概念描述
● 数据的唯一标识:RowKey
● 数据存储在哪个分区,取决于Rowkey处于哪个预分区的区间内。
● 设计RowKey的目的:让数据均匀分布于所有region中,一定程度上防止数据倾斜。
2)设计方案
RowKey除了根据业务和查询需求设计之外,还要注意一下三点
方案 | 说明 | 示例 |
①生成随机数、hash、散列值 | 相近行总存储在相近位置,顺序读>随机读,需要将热点打散 | |
②反转固定格式的数值 | 大数字-小数字 这样新数据就排在前面 | |
③加盐(salting)+ 哈希(hashing) | 加盐前缀种类越多,RowKey越散。为了客户能完整重RowKey,构前缀不可以随机 |
5.3 内存优化
HBase操作需要大量内存,Table可以缓存在内存中,但不应分配过大。
.............