HBase
建立在HDFS之上,提供高可靠性、高性能列存储、列存储、可伸缩、实时读写的分布式数据库系统。
实时读写、随机访问。
海量存储:可以存储大批量数据
列式存储
极易扩展
高并发
稀疏:列为空不占用存储空间
数据的多版本:版本号式插入数据的时间戳
数据类型单一:所有数据在Hbase中以字节数组存储
HBase的数据模型
rowkey行键
table的主键,table中的记录也是按照rowkey字典序进行排序的。
Column Family列族
HBase的每个列,都归属于某个列族
列族是表的一部分,建表时候至少指定一个列族
创建一张表user,有两个列族info、data
create ‘user’,‘info’,‘data’
column列
列是表的某一列族下的一个列
列族名:列名
info:name
cell单元格
cell中的数据没有类型,全部是以字节数组进行存储。
timestamp时间戳
可以对表中cell多次赋值,每次赋值操作的时间戳timestamp,可以看成cell值得版本号version number
Hbase整体架构
Client客户端
是操作HBase集群的入口
对于管理类的操作,如表的增删改操纵,client通过RPC与HMaster通信完成。
ZooKeeper集群
实现了HMaster的高可用性,多HMaster间进行主备选举
保存了HBase的元数据信息meta表,提供了HBase中region的寻址入口的线索数据。
对HMaster和HRegionServer实现了监控
HMaster
HBase集群也是主从架构,HMaster是主的角色,是老大
主要负责Table表和region的相关管理工作:
关于Table
管理Client对Table的增删改的操作
关于Region
在Region分裂后,负责新Region分配到指定的HRegionServer上
管理HRegionServer间的负载均衡,迁移region分布
当HRegionSrever间的负载均衡,迁移region分布
当HRfgionServer宕机后,负责其上的region的迁移。
HRegionServer
HBase集群中从的角色
响应客户端的读写数据请求
负责管理一系列的Region
切分在运行过程中变大的region
Region
HBase集群中分布式存储的最小单元
一个Region对应一个Table表的部分数据
HBase shell命令
shell客户端在bin/habse shell启动
help 'create'#查看具体命令的帮助信息
list #查看当前数据库中有哪些表
#创建user表,表中包含info data两个列族
create 'user','info','data'
create 'user',{NAME='info',VERSIONS=>'3'},{NAME=>'data'}
#put插入数据
#向向user表中插入信息,row key为rk0001,列族info中添加名字为name的列,值为zhansan
put 'user', 'rk0001','info:name','zhangsan'}
#查询表中row key为rk0001的所有信息
get 'user','rk0001','info'
#查看rowkey中指定列族指定字段的值
get 'user','rk001'
get 'uset','rk001','info'
#查看rowkey指定多个列族的信息
get 'user','rk0001','info','data'
get 'user', 'rk0001', {COLUMN => ['info', 'data']}
#指定rowkey与列值过滤器查询
get 'user','rk0001',{FILTER=>"ValueFilter(=,'binary:zhangsan')"}
#获取user表中row key为rk0001,列标识符中含有a的信息
get 'user','rk0001',{FILTER=>"QualifierFilter(=,'substreing:a')"}
#scan查询所有行的数据
scan 'user', {COLUMS =>'INFO'}
#查询user表中列族为info的信息
scan 'user', {COLUMS=>'info'}
#当把某些列的值山粗后,具体的数据并不会马上从存储文件中删除,查询时,不显示被删除的数据,如果想要查出来的话,RAW=>true
scan 'user',{COLUMNS=>'info',RAW=>true,VERSIONS=>5}
#多列族查询
scan 'user',{COLUMNS = >['info','data']}
#查询多个列族与条件模糊查询
#查询user表中列族为info和data且列标识符中含有a字符的信息
scan 'user', {COLUMNS =['info','data'],FILTER =>"QualifierFilter(=,'substring:a')"}
#指定rowkey的范围查询
scan 'user',{COLUMNS => 'info',STARTROW=>'rk0001',ENDROW=>'RK0003'}
#指定rowkey的模糊查询
scan 'user',{FILTER=>"PrefixFilter('rk')"}
#指定数据版本的范围查询 前闭后开
scan 'user', {TIMERANGE => [1392368783980, 1392380169184]}
#更新数据操作版本
alter 'user', NAME =>'info',VERSIONS=>5
#删除数据以及删除表操作
删除user表中row key为rk0001,列为info:name的数据
delete 'user', 'rk0001','info:name'
#删除一个列族
alter 'user', 'delete' =>'info'
alter 'user', NAME=>'info',METHOD=>'delete'
#清空表数据
truncate 'user'
#删除表
disable 'user'#第一步
drop 'user'#第二
#统计一张表有多少行数据
count 'user'
#显示服务器状态
status 'node0'
#显示HBase当前用户
whoami
#展示表结构信息
describe 'user'
#检查表是否存在,适用于表量特别多的情况
exists 'user'
#查看表是否禁用或启动
is_enabled 'user'
is_disabled 'user'
#禁用一张表/启动一张表
disable 'user'
enable 'user'
过滤器
比较运算符
LESS <
LESS_OR_EQUAL <=
EQUAL =
NOT_EQUAL <>
GREATER_OR_EQUAL >=
GREATER >
NO_OP 排除所有
HBase的数据存储原理
一个HRegionServer会负责很多个region
一个region包含很多个store
一个列族就划分成一个store如果一个表中只有1个列族,那么这个表的每一个region中只有一个store
如果一个表中有N个列族,那么这个表中每个region都有N个store
一个store里面只有一个memstore
memstore是一块内存区域,写入的数据会先写入memstore进行缓存,然后再把数据刷到磁盘
一个store里有很多个storeFile,最后数据是以很多个hfile这种数据结构结构的文件保存在HDFS上。
StoreFile是HFile的抽象对象,如果说到StoreFile就等于HFile
每次memstore刷写数据到磁盘,就会生成对应的一个新的HFile文件出来。
HBase读数据
HBase集群,只有一张meta表,此表只有一个region,该region数据保存在一个HRegionServer上。
HBase写数据
补充:
HLog(write ahead log):
也称为WAL意为Write ahead log,类似mysql中的binlog,用来做灾难恢复时用,HLog记录数据的所有变更,一旦数据修改,就可以从log中进行恢复。
HBase的flush、compact机制
Flush触发条件
flush()意思是把缓冲区的内容强制的写出。
- memstore级别限制:当Region中任意一个MemStore的大小达到上限,会触发Memstore刷新。
- region级别限制:当Region中所有的Memstore的大小综合达到了上限,会触发memstore刷新。
- Region Server级别限制:当一个Region Server中所有的Memstore的大小综合超过低水位阈值,RegionServer开始强制flush。先fush memstore最大的region,再执行次大的,一次执行。如果写入速度大于flush写出的素的,导致总memstore大小超过高水位阈,会阻塞更新执行flush,直到总memstore低于低水位阈值。
- Hlog数量上限:当一个region server中的HLog数量达到上限时,系统会选取最早的一个HLog对应的一个或多个region进行flush
- 定期刷星memstore:默认周期未1小时,确保memstore不会长时间没有持久化。为了避免所有的memstore在同意世纪那都进行了flush导致的问题,定期的flush有20000左右的随即延。
- 手动flush:用户通过flush ’tablename‘或者’flush name‘分别对一个表或者一个Region进行flush
flush的流程
为了减少flush过程对读写的影响,将整个flush过程分为三个阶段:
prepare阶段:遍历当前Region中所有的Memstore,将Memstore中当前数据集CellSkipListSet做一个快照snapshot,然后再新建一个CellSkipListSet。后期写入的数据都会写入新的中。prepare阶段需要加一把updatelock对写请求堵塞,结束之后释放该锁,因此次阶段没有任何费时操作,因此持锁时间很短。
flush阶段:遍历所有Memstore,将prepare阶段生成的snapshot持久化为临时文件,临时文件会统一放到目录.tmp下。这个过程因为涉及到磁盘IO操作,因此相对比较耗时。
commit阶段:遍历所有Memstore,将flush阶段生成的临时文件移到指定的ColumnFamily目录下,针对HFile生成对应的storefile和Reader,把storefile添加到HStore的storefiles列表中,最后再清空prepare阶段生成的snapshot。
compact合并机制
hbase为了防止小文件过多,以保证查询效率,所以hbase需要在必要的时间将这些小的store file合并成相对较大的store file,这个过程称之为compaction。
在hbase中主要存在三种类型的compaction合并
in memory compaction内存合并
minor compaction 小合并
major compaction 大合并
in memory compaction 内存合并
MemoryStore的组成部分:
segment:compacting memstore中,数据是以segment作为单位进行组织。memory store中每个内存区域都是一个segment:如active、snapshot
active:可读 科协的内存区域
snapshot :只读的内存区域,即将被flush到磁盘
- 数据写入时首先写入active中,当active满之后,会被移动到pipeline中,这个过程称为in-memory flush。pipeline中包含多个segment,其中的数据不可修改。compacting memstore会在后台将pipeline中的多个segment合并为一个更大、更紧凑的segment,这就是compaction的过程。
- 如果regionserver需要把memstore的数据flush到磁盘,会首先选择其他类型的memstore,然后选择compacting memstore因为其对内存的管理更有效率,所以延长它的生命周期可以减少总的I/O。
- 当Compacting Memstore被flush到磁盘时,pineline中的所有segment会被转移到snapshot中进行合并然后写入Hfile
compaction策略:
Basic:不清理多余的数据版本,不需要对cell的内存进行拷贝,适用于所有写入模式。
Eager:会过滤重复的数据,并清理多余的版本,这意味着会有额外的开销。主要针对数据大量淘汰的场景:例如消息队列、购物车等。
Adaptive:根据数据的重复情况来决定是否使用Eager策略,在Adaptive策略中,首先会对待合并的segment进行评估,方法是在已经统计过不重复key个数的segment中,找出cell个数最多的一个,然后用这个segment的numUniqueKeys / getCellsCount得到一个比例,如果比例小于设定的阈值,则使用Eager策略,否则使用Basic策略。
minor compaction 小合并
将store中多个hfile合并为一个Hfile,在这个过程中会选取一些小的、相邻的storefile将他们合并成一个更大的storefile,不会物理删除,只是做标记。
major compaction大合并
合并store中所有的hfile作为一个HFile。
将所有的storefile合并成一个storefile,会清理三类无意义的数据:被删除的数据、TTL过期数据、版本号超过设定版本号的数据。合并频率比较低,默认7天执行一次,并且性能消耗非常大,建议生产关闭(设置为0),在应用空闲时间手动触发。一般可以是手动控制进行合并,防止出现在业务高峰期。
HBase表的预分区
pre-splitting
当一个table刚被创建时,HBase默认的分配一个region给table。这样就可能导致所有的读写请求都会访问到同一个regionserver的同一个region中,达不到负载均衡的效果。
增加数据读写效率
负载均衡,防止数据倾斜
方便集群调度region
优化map数量
每一个region维护着startROW与endRowKey,如果加入的数据符合某个region维护的rowkey烦诶,该数据交给这个region维护。
手动指定预分区
方式一
create 'person','info1','info2',SPLITS => ['1000','2000','3000','4000']
方式二
cd /kkb/install#分区规则在文件中
vim split.txt
aaa
bbb
ccc
ddd
create 'student','info',SPLITS_FILE => '//split.txt'
方式三
exStringSplit会将数据从“00000000”到“FFFFFFFF”之间的数据长度按照n等分之后算出每一段的起始rowkey和结束rowkey,以此作为拆分点。
create 'mytable', 'base_info',' extra_info', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
HBase与Hive的对比
Hive
数据仓库管理系统
Hive的本质就相当于将HDFS中已经存储的文件在mysql中做一个双射关系,以方便使用HQL去管理查询。
用于数据分析、清洗
适用于离线的数据分析和清洗,延迟较高
基于HDFS、MR
Hive存储的数据依旧在datanode上,编写的HQL语句终将是转换为MapReduce代码执行。
HBase
数据库管理系统
是一种面向列存储的非关系型数据库
用于存储结构化和非结构化的数据
适用于单表非关系型数据的存储,不适合做关联存储,类似join等操作。
基于HDFS。
数据持久化存储的体现形式是Hfile,存放于DataNode中,被RegionServer以region的形式进行管理。
延迟较低,接入在线业务使用。
面对大量的企业数据,HBase可以直先单表大量数据的存储,同时提供了高效的数据访问速度。
总结
Hive和Hbase是两种基于Hadoop的不同技术,Hive是一种类SQL的引擎,并且运行MapReduce任务,Hbase是一种在Hadoop之上的NoSQL 的Key/vale数据库。这两种工具是可以同时使用的。就像用Google来搜索,用FaceBook进行社交一样,Hive可以用来进行统计查询,HBase可以用来进行实时查询,数据也可以从Hive写到HBase,或者从HBase写回Hive。
rowkey的设计
二进制码流,可以是任意字符串,最大长度64kb实际应用中一般为10-100bytes,以byte[]形式保存,设计为定长。
建议尽可能短,也不能太短。
散列原则
建议将rowkey的高位作为散列字段,这样将提高数据均匀分布在每个regionserver,来实现负载均衡的几率。
热点问题
预分区
加盐:rowkey前面增加随机数,具体是给rowkey分配一个随即前缀
哈希
反转(牺牲了有序性)