Hbase原理| 优化

Hbase原理| 优化HBase的设计目标就是为了那些巨大的表,如数十亿行、数百万列。面向列,准确的说是面向列族。每行数据列可以不同。架构HMaster会到ZK中进行注册,ZK中一主二备;当主宕机时,zk通知备机,备机中选择一个当主机;HRegionServer负责数据的存储读写;HMaster做负载均衡数据均

大家好,欢迎来到IT知识分享网。

 

HBase的设计目标就是为了那些巨大的表,如数十亿行、数百万列。

面向列,准确的说是面向列族。每行数据列可以不同。

 架构

HMaster会到ZK中进行注册,ZK中一主二备; 当主宕机时,zk通知备机, 备机中选择一个当主机;
HRegionServer负责数据的存储读写;
HMaster做负载均衡数据均匀的分配给HRegionServer,它负责管理HRegionServer;
HLog-WAL(预写日志,日志格式为HLog)记录对数据的增删改,写数据之前先记录在HLog(它也不是实时的同步)里边,在小的时间间隔做同步到DataNode

1个Region–对应–>1个Hbase表一个表可以一个或有多个HRegion,一个HRegion不能存储多个表;
1个store–对应–>1个列族;每个store存放一个列族
把内存中数据先存放在–>Mem Store,达到阈值–StoreFile(HFile的格式)放到—>HDFS Client–>DataNode

列是最小单元
Hbase处理10亿行,百万列数据是先把hbase表会做水平切分,每一份放一个region;
列族数<=2-3个,不然等到它的flush机制,刷写的列族会很多;

Hbase原理| 优化

 

HBase是由Client、Zookeeper、Master、HRegionServer、HDFS等几个组件组成
①Client
Client包含了访问HBase的接口,另外Client还维护了对应的cache来加速Hbase的访问,比如cache的.META.元数据的信息。

②Zookeeper:
HBase通过Zookeeper来做Master的高可用、RegionServer的监控(容灾性)、元数据的入口以及集群配置的维护等工作。具体工作如下:
(1)通过Zoopkeeper来保证集群中只有1个Master在运行,如果Master异常,会通过竞争机制产生新的Master提供服务
(2)通过Zoopkeeper来监控RegionServer的状态,当RegionSevrer有异常的时候,通过回调的形式通知Master RegionServer上下线的信息,master会把宕机的数据给恢复了给其他RegionServer
(3)通过Zoopkeeper存储元数据的统一入口地址
③ Master
Master节点的主要职责如下:
监控RegionServer| 处理RegionServer故障转移| 通过Zookeeper发布自己的位置给客户端

(1)为RegionServer分配Region;
(2)维护整个集群的负载均衡;
(3)维护集群的元数据信息;(有多少个RegionServer,存了多少个Region,每个Region存多大数据)
(4)发现失效的Region,并将失效的Region分配到正常的RegionServer上;
(5)当RegionSever失效的时候,协调对应Hlog的拆分;
④ RegionServer
HregionServer负责存储HBase的实际数据|维护Hlog| 执行压缩
。它的功能概括如下:
(1)管理master为其分配的Region;
(2)处理来自客户端的读写请求;
(3)负责和底层HDFS的交互,存储数据到HDFS(刷新缓存到HDFS);
(4)负责Region变大以后的拆分(分片);
(5)负责Storefile的合并工作;
⑤ HDFS
HDFS为HBase提供最终的底层数据存储服务,同时为HBase提供高可用(Hlog存储在HDFS)的支持,具体功能概括如下:
(1)提供元数据和表数据的底层分布式存储服务
(2)数据多副本,保证的高可靠和高可用性
Write-Ahead logfile
HBase的修改记录,当对HBase写数据的时候,数据不是直接写进磁盘,它会在内存中保留一段时间(时间以及数据量阈值可以设定)。但把数据保存在内存中可能有更高的概率引起数据丢失,为了解决这个问题,数据会先写在一个叫做Write-Ahead logfile的文件中,然后再写入内存中。
Region
Hbase表的分片,HBase表会根据RowKey值被切分成不同的region存储在RegionServer中,在一个RegionServer中可以有多个不同的region。
Store
HFile存储在Store中,一个Store对应HBase表中的一个列族
MemStore
就是内存存储,位于内存中,用来保存当前的数据操作,所以当数据保存在WAL中之后,RegsionServer会在内存中存储键值对。
StoreFile
这是在磁盘上保存原始数据的实际的物理文件,是实际的存储文件。StoreFile是以Hfile的形式存储在HDFS的。Hfile是一种文件格式,例如txt、orc、parquet等
RowKey
是用来检索记录的主键。访问HBASE table中的行,只有三种方式:
  1)通过单个RowKey访问
  2)通过RowKey的range(正则)
  3)全表扫描
在HBASE内部,RowKey保存为字节数组。存储时,数据按照RowKey的字典序(byte order)排序存储。设计RowKey时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。(位置相关性) ;  hbase中的rowkey 三大设计原则: 唯一性、长度原则、散列原则
Column Family
列族:HBASE表中的每个列,都归属于某个列族。列族是表的schema的一部 分(而列不是),必须在使用表之前定义。列名都以列族作为前缀。例如 courses:history,courses:math都属于courses 这个列族。
Cell
{rowkey, column Family:column} 唯一确定的单元。cell中的数据是没有类型的,全部是字节码形式存贮。
Time Stamp
版本通过时间戳来索引,为64位长整型;

不同版本的数据按照时间倒序排序,即最新的数据排在最前面。

命名空间

HBase命名空间 namespace 是与关系数据库系统中的数据库类似的表的逻辑分组

 

HBase原理

元数据有2类:
master 有几个regionserver,regionserver中有几个region,region中的数据量有多大
regionserver,hbase所有数据存储的位置,对应rowkey

读流程

Hbase原理| 优化

读数据rowkey存到哪里了?
client-->zk(meta-region-server)
它存储元数据所在位置,meta存在RS中

[zk: localhost:2181(CONNECTED) 9] get /hbase/meta-region-server
�regionserver:16020+��PBUF

        hadoop101

scan 'hbase:meta'
column=info:server, timestamp=1551919444973, value=hadoop101:16020 
column=info:regioninfo,timestamp=1551919444973, value={ENCODED=>XX, NAME=>'student,XXX', STARTKEY =>'', ENDKEY => ''}
一张表可能分布在不同region中,meta中记录这个region是从哪一行到哪结束;


存储时会有一个meta
rowkey存放到哪个RS中
client第一次读取会缓存rowkey在哪

写流程

 Hbase原理| 优化

Mem Store内存节点,预写日志WAL,格式Hlog
①先写入HLog(磁盘)
②再写入Mem Store中
③如果HLog落盘失败,Mem Store就会回滚,请求写数据失败,保证了数据的一致性

 

数据flush过程

Flush:
1)region级别的flush:
Mem Store
①默认128M
②region中有多个Mem Store,region中所有的MamStore达到128*4,触发整个region的flush
③memstore数据存储超过1h
flush刷写最小单位是region而不是MemStore;而判断标准是region

2)regionserver级别的flush :
regionserver,多个region
高点:memstore占了 0.4*java虚拟机的堆空间—>展开flush,并阻塞写操作;
会先flush占内存最大的memstore,刷到低点(jvm堆*0.4*0.95)就停止flush,不再阻塞写操作;

 数据切分和合并过程

split:
1)一张表可能有一个或多个region;随着数据量增加,store会把数据分到另外一个region中,这样数据量就会减半,并发量增加,提高了读写性能;
store(1个store对应HBase中1个列族)分裂最大体量10G
一个点越长越多,而不是越长越大;
接受master调度,使region在regionserver中均匀的分布

HBase通常会根据hbase-default.xml和hbase-site.xml 配置文件中的设置来处理您所在区域的分割。重要的设置包括:hbase.regionserver.region.split.policy,hbase.hregion.max.filesize,hbase.regionserver.regionSplitLimit。分割的一个简单的观点是,当一个区域发展到hbase.hregion.max.filesize时,它被分割。对于大多数使用模式,您应该使用自动分割。

查看IncreasingToUpperBoundRegionSplitPolicy,可知切分规则:

 
Math.min(tableRegionsCount^3 * initialSize,defaultRegionMaxFileSize)
1) tableRegionCount:当前表在所有RegionServer上拥有的所有的Region数量的总和
2) initialSize:如果定义了hbase.increasing.policy.initial.size,则使用该值,否则用memstore刷写值得2倍,即hbase.hregion.memstore.flush.size*2
3) defaultRegionmaxFileSize: hbase.hregion.max.filesize,也就是Region的最大大小
4) Math.min:取这两个数值的最小值

例如当初始hbase.hregion.memstore.flush.size定义为128M,过程为:
1)当只有一个Region,min(256M,10G),也就是说store File达到256M触发分裂;(2*128,10G)
2)当有2个Region,min(2048M,10G), store File达到2048M触发分裂;(2^3*128,10G)
3)当有3个Region,min(6912M,10G), store File达到6912M触发分裂;
4)当有4个Region时候,为min(16G,10G),上限达到了10GB,store File达到10G就触发分裂,此后,Region数量再增加也不会增加上限

 

涉及到的相关配置有(hbase-site.xml中配置):
拆分策略的初始化大小
hbase.increasing.policy.initial.size
memstore最大刷写值
hbase.hregion.memstore.flush.size
固定大小拆分策略定义的最大Region大小
hbase.hregion.max.filesize

compact:合并
分裂足够多了就会合并;
1)每隔7day, 每个region的所有file会进行合并,mamstore写出生成一个file;
2)store每次flush都会生成一个storefile,达到3个时将触发合并;拆的太散就合

 

 HBase优化

高可用

在HBase中Hmaster负责监控RegionServer的生命周期,均衡RegionServer的负载,如果Hmaster挂掉了,那么整个HBase集群将陷入不健康的状态,并且此时的工作状态并不会维持太久。所以HBase支持对Hmaster的高可用配置。

在conf目录下创建backup-masters文件;在backup-masters文件中配置高可用HMaster节点
    [kris@hadoop101 conf]$ vim backup-masters
      hadoop102
将整个conf目录scp到其他节点
    xsync backup-masters

预分区

每一个region维护着startRow与endRowKey,如果加入的数据符合某个region维护的rowKey范围,则该数据交给这个region维护。那么依照这个原则,我们可以将数据所要投放的分区提前大致的规划好,以提高HBase性能。

预分区(结合rowkey的设计用)是为了解决:

①热点问题:
  多个客户端读写一个regionserver
②切分(数据量大时)时会影响读写:

手动设定预分区

 
hbase> create 'staff1','info',SPLITS => ['10','20','30','40']

三种:
00-10
10-20
20-30
30-40
一共分了5个区
hbase(main):005:0> put 'staff', '2001', 'info:name', 'alex'
0 row(s) in 0.1050 seconds

2001是被分到了20-30这个区,因为它是按照字典顺序排序的;先比较第一个,再比较第二个...
 

Hbase原理| 优化

 

 
按照文件中设置的规则预分区
创建splits.txt文件内容如下:
[kris@hadoop101 hbase-1.3.1]$ vim splits.txt 
aaaa
bbbb
cccc
dddd
然后执行:
create 'staff2','info',SPLITS_FILE => 'splits.txt'
 

Hbase原理| 优化

 
生成16进制序列预分区
create 'staff3','info',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}

                11111111
11111111    22222222
22222222    33333333
...
dddddddd    eeeeeeee
eeeeeeee
 

使用JavaAPI创建预分区

 
//自定义算法,产生一系列Hash散列值存储在二维数组中
byte[][] splitKeys = 某个散列值函数
//创建HBaseAdmin实例
HBaseAdmin hAdmin = new HBaseAdmin(HBaseConfiguration.create());
//创建HTableDescriptor实例
HTableDescriptor tableDesc = new HTableDescriptor(tableName);
//通过HTableDescriptor实例和散列值二维数组创建带有预分区的HBase表
hAdmin.createTable(tableDesc, splitKeys);
 

 

预分区:
create  'dmp_wanka',
{NAME => 'info',BLOOMFILTER => 'ROWCOL',COMPRESSION => 'SNAPPY'},
{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'},
{NAME => 'app',BLOOMFILTER => 'ROWCOL',COMPRESSION => 'SNAPPY'},
{NUMREGIONS => 9, SPLITALGO => 'HexStringSplit'}

 

RowKey设计

设计rowkey的主要目的 ,就是让数据均匀的分布于所有的region中,在一定程度上防止数据倾斜。解决热点问题,均匀分布

 rowkey,不要超过16字节;数据是以kv形式存储在hfile,过多占空间内存,影响Hfile的存储效率; memstore要缓存部分数据到内存,也会占用内存空间。使得内存利用率降低;

1. 哈希

哈希会使同一rowkey的数据永远在同一个region中。哈希也可以使负载分散到整个集群,但是读却是可以预测的,可以使用get操作准确获取某一个行数据

比如:
原本rowKey为1001的,哈希后变成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7
原本rowKey为3001的,哈希后变成:49042c54de64a1e9bf0b33e00245660ef92dc7bd
原本rowKey为5001的,哈希后变成:7b61dec07e02c188790670af43e717f0f46e8913

在做此操作之前,一般我们会选择从数据集中抽取样本,来决定什么样的rowKey来Hash后作为每个分区的临界值

字符串反转

反转行键固定宽度或数字,以便最经常改变的部分在第一位。这有效地使行键随机化,但牺牲了行排序属性。

20170524000001转成10000042507102
20170524000002转成20000042507102

时间戳反转 -取反

一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用3.时间戳反转 -取反

可以用Long.Max_Value – timestamp追加到rowkey的末尾

例如[rowkey][ Long.Max_Value – timestamp],[rowkey]的最新值可以通过scan [rowkey]获得[rowkey]的第一条记录,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。比如需要保存一个用户的操作记录,按照操作时间倒序排序,在设计rowkey的时候,可以这样设计 [userId反转][Long.Max_Value – timestamp],在查询用户的所有操作记录数据的时候,直接指定反转后的userId,startRow是[userId反转][000000000000],stopRow是[userId反转][Long.Max_Value – timestamp] 。

如果需要查询某段时间的操作记录,startRow是 [userId反转][Long.Max_Value – 结束时间],stopRow是[userId反转] [Long.Max_Value – 起始时间]。

Salting(加盐)

在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。分配的前缀种类数量应该和你想使用数据分散到不同的region的数量一致。加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点。

 
A_foo0003
B_foo0001
C_foo0004
D_foo0002
E_foo0001
加盐的一个缺点:同一个key的数据可能不一样;
 

内存优化

HBase操作过程中需要大量的内存开销,毕竟Table是可以缓存在内存中的,一般会分配整个可用内存的70%给HBase的Java堆。但是不建议分配非常大的堆内存,因为GC过程持续太久会导致RegionServer处于长期不可用状态,一般16~48G内存就可以了,如果因为框架占用内存过高导致系统内存不足,框架一样会被系统服务拖死。conf/env.sh; export: HBASE_HEAPSIZE=1G

基础优化

1.允许在HDFS的文件中追加内容

hdfs-site.xml、hbase-site.xml

属性:dfs.support.append

解释:开启HDFS追加同步,可以优秀的配合HBase的数据同步和持久化。默认值为true。

2.优化DataNode允许的最大文件打开数

hdfs-site.xml

属性:dfs.datanode.max.transfer.threads

解释:HBase一般都会同一时间操作大量的文件,根据集群的数量和规模以及数据动作,设置为4096或者更高。默认值:4096

 

3.优化延迟高的数据操作的等待时间

hdfs-site.xml

属性:dfs.image.transfer.timeout

解释:Fsimage文件传输超时时间,建议把该值设置为更大的值(默认60000毫秒),以确保Fsimage传输不会被timeout掉。

4.优化数据的写入效率

mapred-site.xml

属性:
mapreduce.map.output.compress
mapreduce.map.output.compress.codec
解释:开启这两个数据可以大大提高文件的写入效率,减少写入时间。第一个属性值修改为true,第二个属性值修改为:org.apache.hadoop.io.compress.GzipCodec或者其他压缩方式。

 

5.设置RPC监听数量

hbase-site.xml
属性:hbase.regionserver.handler.count
解释:默认值为30,是regionserver上用于等待响应用户请求的线程数,读写请求较多时,增加此值。

6.优化HStore文件大小
hbase-site.xml
属性:hbase.hregion.max.filesize
解释:该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分为两个Hfile。默认值10737418240(10GB),如果需要运行HBase的MR任务,可以减小此值,因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。

7.优化hbase客户端缓存
hbase-site.xml
属性:hbase.client.write.buffer
解释:用于指定HBase客户端写缓存,增大该值可以减少RPC调用次数,但是会消耗更多内存,反之则反之。一般我们需要设定一定的缓存大小,以达到减少RPC次数的目的。

8.指定scan.next扫描HBase所获取的行数
hbase-site.xml
属性:hbase.client.scanner.caching
解释:用于设置HBase scanner一次从服务端抓取的数据条数,默认情况下一次一条。通过将其设置成一个合理的值,可以减少scan过程中next()的时间开销,但是需要通过客户端的内存来缓存这些记录。值越大,消耗内存越大。

9.flush、compact、split机制

当MemStore达到阈值,将Memstore中的数据Flush进Storefile;compact机制则是把flush出来的小文件合并成大的Storefile文件。split则是当Region达到阈值,会把过大的Region一分为二。
涉及属性:
即:128M就是Memstore的默认阈值
hbase.hregion.memstore.flush.size:134217728
即:这个参数的作用是当单个HRegion内某一Memstore大小总和超过指定值时,flush该HRegion的所有memstore。RegionServer的flush是通过将请求添加一个队列,模拟生产消费模型来异步处理的。那这里就有一个问题,当队列来不及消费,产生大量积压请求时,可能会导致内存陡增,最坏的情况是触发OOM。

hbase.regionserver.global.memstore.upperLimit:0.4
hbase.regionserver.global.memstore.lowerLimit:0.38
即:当MemStore使用内存总量达到hbase.regionserver.global.memstore.upperLimit指定值时,将会有多个MemStores flush到文件中,MemStore flush 顺序是按照大小降序执行的,直到刷新到MemStore使用内存略小于lowerLimit

 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32528.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信