HBase总结
一、数据模型
1.数据模型例子
2.数据模型解析
1)存储(keyvalue)
HBase什么样的数据都能储存,数据的话在HBase当中都是以字节数组的形
式储存的;HBase中数据的存储是以key-value格式来存储的,key是rowkey+时
间戳+列簇,valuValue部分没有那么复杂的结构,就是纯粹的二进制数据
引用原文:https://blog.csdn.net/ping_hu/article/details/77115998
和https://blog.csdn.net/weixin_33750452/article/details/90308038
2)Row Key
<1> rowkey介绍
如果你想对HBase的表进行防问的时候必须通过row key,那么row key是什
么呢:Row Key代表了一行数据;它可以是任意的字符,但是最大只有64k;并
且按照字典排序的;
注:我们可以利用字典排序这个点,将经常使用的数据放在一块,最近要访
问的放在一块,来进行小小的优化一下
<2> rowkey设计
row key设计的时候需要注意的是,row key的设计规则,规则有这么几个
定长
为什么定长呢?那是以为内在HBase当中,row的排序是按照字典排序
的,如果不定长的话,排序就有可能会打乱。
越短越好
为什么定长呢?那是以为内在HBase当中,每条数据都会呆着rowkey,
所以说rowkey越长,所消耗掉额空间就越多,适当的减少rowkey的长度可以提
高存储空间的利用
唯一
按照实际的业务来
3)CF(Clumu Family)
· 列簇的话,它是shcema的一部分,所以它必须预先给出;
· 在HBase表中,列名以列簇为前缀,一个列簇可以有很多个成员(列);
· 成员的话可以按照业务的需求随时追加(动态加入);
· HBase存储把同一个列簇下的数据放在同一个目录下,就是说是以列簇
为目录存储的,目录下的文件存储该列簇的数据;
· 需要注意的是列簇一般最多只能有三个,一般只用一个就行,这是因为
当一个列簇flush的时候,因为关联效应其他的列簇同样也会flush,最
终导致系统产生更多的IO。
4)TimeTamp
时间戳是有系统生成的,精确到毫秒的64位整数,而且它本身就代表了
唯一性;在HBase当中每个cell存储单元对同一份数据有多个版本,而版本
是根据时间戳来区分的,并且这些版本是按照时间倒序排序的,最新的数据
版本排在前面的。
5)cell单元格
是row key和列簇交叉决定的,并且是带有版本的;
实际上存储的是一些未解析的字节数组,由row key, clumn(family |
qualifier), version来定位。
6)Hlog
Hlog其实就是一个普通的hadoop序列文件,它会记录你对HBase表的
操作,也会记录你操作的数据。它的key是HLogKey对象,HLogKey中记录了写
入数据的归属信息,比如table和region的名字,还有时间戳和序列号,时间戳
的值是写入的时间,而序列号的初始值是0,或者是最近一次的写入时间。
7)注意事项
row的设计和列簇的设计
二、HBase架构
架构图
1.架构解析
1)client
包含HBase的接口,并维护cache来加快对HBase的访问
2)zookeeper
保证在任意时刻,只有一个Master是在工作状态的;
并且存储了region的寻址入口;
以及HBase的shcame和表的元数据;
它还有一个作用就是实时的监控者region server的上线和下线状态,并通知
给Master,就像个秘书一样。
3)Master
管理region server的负载均衡和管理用户对表的增删改查;
在一个即使负责为regionserver分配region,以及发现失效的regionserver并
重新分配region。
4)RegionServer
负责region的维护以及region的IO请求,还有即使负责将膨胀的region进
行切分
5)Region
<1>介绍
先介绍一下region,HBase会吧一张表分成多个区域,每个区域就是一个
region,region里面保存的是某一段连续的数据,刚开始的时候就只有一个region,
当随着数据的不断插入,region到达某个阀值的时候,这个region就会等分裂变
为两个region随着region的不断增多,master会把它分配到不同的节点上,所
以说一张表也有可能分配到不同的regionserver上。
而一个region又是由多个store组成的,一个store对应的是一个列簇,这是
他们之间的关系,我接着说一下store
<2>Store
Store包含了位于内存的memestore和位于磁盘的storeFile,当进行写入操作
的时候,数据会先写入memstore,当memestore到达某个阀值,regionserver
会启动flashcache,将memestore的数据写入到磁盘,形成一个新的storefile
<3>StoreFile
当storefile增大到一个阀值以后,系统会进行合并,在版本合并过程中,系
统会进行版本合并和删除工作,合并成一个更大的storrefile;
当storefile的大小和数量都达到一个阀值以后,region会进行裂变分裂成两
个相等的region,然后由master分配,实现负载均衡
<4>Memestore
Memestore的就是一个内存缓冲区,当这个缓冲区满的时候就会溢写数据到
磁盘形成新的storefile,当客户端检索数据的时候,会先从memestore中检索,
检索不到再到storefile中检索
<5>合并(compaction)
说架构的时候可以扯到这个上,合并是发生在写文件的时候,合并的作用是
合并小文件;清楚过期,多余的版本数据;提高读写数据的效率
<6>注意事项
region是HBase中最小的存储和负载均衡的最小单元,最小单元也就意味着
分布在不同的regionserver上,而一个region由多个store组成,每个store就是
一个列簇,每个store又是由一个memstore和0个或者多个storeFile组成。最
终的数据是以HFile的格式存储在HDFS上的,最终数据就是storeFile
三、HBase优化
1.热点问题优化
1)热点现象以及原因
热点问题是指客户端的大量的访问并只在一个节点上访问,这是热点问 题。产生的原因主要是因为大量相似的rowkey都在一个节点上
解决方案
· 有一种解决方案是加盐,这所谓的加盐,是在row key前面加上随机数,
让rowkey之间的差异化变大,至于加多少个随机数就要看你想要分到多
少个region了。加盐以后的rowkey就会根据随机生成的前缀分配到不同
region上去,避免热点问题。这是加盐
· 将rowkey进行反转也能解决热点问题,虽然这样可以解决热点问题,但
是也牺牲了rowkey的有序性
· 使用哈希也可以解决这个问题,将哈希作为rowkey的前缀。
2)表设计
<1>预分区
HBase默认建表的时候只有一个region,在数据写入时,只会往这一个
中写入,这就有两个问题,第一个数据都往一个region上写,会有热点问题,
第二个当region足够大的时候要进行切分,会消耗集群的IO资源。我们在
建表的时候添加一些空的region来预防这两个问题,创建包含预分区表的命
令如下:
> create 't1', 'cf', SPLITS => ['20150501000000000', '20150515000000000',
'20150601000000000']
<2>rowkey的设计
唯一性;rowkey默认字典升序排序;越短越好,定长;散列;取反;
Has;根据实际的业务来
<3>clumn family的设计
一张表中最多不要定义超过三个,一般一个就行。这么做是因为,如果
在有多个列簇的情况下,其中一个flush的时候,它邻近的列簇因为关联效应也
会flush,最终导致系统产生更多的IO。还有就是当region到达阀值的时候,要
进行裂变了,假设这个region中有两个列簇,一个列簇100000行数据,一个100
行数据,这样就会导致100的列同样被分到多个region中,当查询的时候效率会
变低
<4>参数优化
设置表在regionserver缓存:In Memory
HClumnDiscriptor.setInMemory(true)
设置表的最大版本数:Max Versions
HClumnDiscriptor.setMaxVersions(int versions)
设置表的存储时间:Time To Live
HClumnDiscriptor.setTimeToLive(int TimeToLive)
<5>compation
HBase为了防止被刷到磁盘的memorstore的文件太小和过多,以及为了
整合storeFile,以保证查询效率,HBase在必要的时候会进行合并,这个过
程叫做compation
分类
· minor conpaction:minor conpaction的作用是将小文件进行合并
优化建议(按照实际需求修改下列参数)
· hbase.hstore.compaction.min :默认值为 3,表示一次minor
compaction中最少选取3个store file. minor compaction才会启动
· hbase.hstore.compaction.max默认值为10,表示一次minor
compaction中最多选取10个store file
· hbase.hstore.compaction.min.size 表示文件大小小于该值的store file
一定会加入到minor compaction的store file中
·hbase.hstore.compaction.max.size 表示文件大小大于该值的store file
一定会被minor compaction排除
·hbase.hstore.compaction.ratio 将store file按照文件年龄排序(older to
younger),minor compaction总是从older store file开始选择
· major compaction: major compaction试讲所有的storeFile合并成一个大
的storeFile
major compaction触发条件
major compact命令
major compact()API
region Server自动运行
优化建议是将系统的默认启动改为手动启动
3)写表优化
<1>多table并发写
创建多个HTable客户端用于写操作,提高写数据的吞吐量
<2>参数设置
· 关闭自动Flush:将这个参数HTable.setAutoFlush(false)设置为false以后,系
统就不用一条数据一更新了,而是等客户端的缓存满了以后再更新,这样就
大大减少了flush的次数
· 设置写数据的缓存大小:将HTable.setWriteBufferSize(WriteBufferSize)这个参
数的值设置为实际要写入数量的值,如果实际写入Buffer中的数据量大于这
个值的时候,buffer就会将数据flush到服务端。
4)读表优化
<1>多table并发读
创建多个HTable客户端用于读操作,提高读数据的吞吐量
<2>HTabke参数设置
· Scanner Caching:将HBase.Client.Scanner.Caching这个参数设置为一个合理的
值,可以减少Scann过程中next()的时间开销,它的代价就是需要客户端
通过内存来维持这些cashe的行为记录
· Scan Attribute Selection:将scan.addColumn("cf1".getBytes(),
"name".getBytes());指定列簇来读取,可以减少网络传输的数据量
· Close ResultScanner:释放资源
scan取完数据后,要关闭ResultScanner来释放资源再就是使用安全的
HTbalePool因为HTbalePool可以自动创建HTble对象,这就解决HTbale线程
不安全的的问题还有HTablePool和HTbale是公用的congfiguration连接的,
可以减少网络开销再就是使用安全的HTbalePool
四、HBase读写流程
1.写流程
[if !supportLists]1)[endif]Client端先访问zookeeper,通过mate表获取region的信息,并且读取
meta表中的数据根据nameSpace、表名和rowkey在mate表中找到对应的region
信息接着通过这个region,找到对应的regionserver
[if !supportLists]2)[endif]把数据分写在memostore和Hlog上一份,这么做是为了防止memostore
中的数据丢失,可以使用Hlog来恢复
[if !supportLists]3)[endif]我们都知道数据写入的时候会先写入位于内存的memstore,当到达
memstore存储的80%的时候,memstore会溢写到磁盘,成为一个新的shtoreFile
文件,我们也都知道当storeFile文件到达一定阀值的时候,系统会进行一次合并,
将小的storeFile文件合并成一个大的StoreFile文件,当storeFile文件的大小和数
量都到达一个阀值的收,当前region就会等分裂变为两个region,接着通过master
分配到对应的regionserver上去。
2.读流程
[if !supportLists]1)[endif]client先访问zookeeper,通过meta表获取region信息,并且读取mate
表中的数据
[if !supportLists]2)[endif]接着在通过namespace、表名以及rowkey在mate表中获取对应的region
信息通过这个region信息呢,找到对应的regionserver信息这样的话数据的路径
就知道了,接着我们就通过这个路径找到对应的rergion
[if !supportLists]3)[endif]读取的时候是先去memstore查找,如果没有的再去storeFile中查找,这
么做是因为系统设置的就是这么做