HBase集群优化篇
HBase集群优化篇
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.HBase的高可用实战案例
博主推荐阅读: https://www.cnblogs.com/yinzhengjie2020/p/12274860.html
二.HBase预分区
博主推荐阅读: https://www.cnblogs.com/yinzhengjie2020/p/12914075.html
三.rowkey设计原则
一条数据的唯一标识就是rowkey,那么这条数据存储于哪个分区,取决于rowkey处于哪个一个预分区的区间内,设计rowkey的主要目的 ,就是让数据均匀的分布于所有的region中,在一定程度上防止数据倾斜。
接下来我们就谈一谈rowkey的设计原则及常用的设计方案。
1>.rowkey的三大设计原则
(1)唯一性原则: 这个很好理解,RowKey的角色类似于关系型数据库当中的主键,因此Rowkey不能重复。 举个例子,使用用户姓名作为RowKey就很不适合,究其原因是因为姓名太容易重复了,如果非要用姓名作为RowKey就得考虑加一些后缀来做区分。 rowkey在设计上保证其唯一性。rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。
(2)长度原则: 而设计太长会导致占用更多的存储空间影响查询效率,设计的太短对业务要求查询也不是特方便。因此在能满足查询条件的情况下,RowKey设计的越短越好。 虽然RowKey最大长度是64KB,实际应用中长度一般为10-100bytes。以byte[] 形式保存,一般设计成定长。
建议越短越好,不要超过16个字节,原因如下:
(a)数据的持久化文件HFile中是按照KeyValue存储的,如果rowkey过长,比如超过100字节,1000w行数据,光rowkey就要占用100*1000w=10亿个字节,将近1G数据,这样会极大影响HFile的存储效率;
(b)MemStore将缓存部分数据到内存,如果rowkey字段过长,内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率。
(c)目前操作系统都是64位系统,内存8字节对齐,控制在16个字节,8字节的整数倍利用了操作系统的最佳特性。 (3)散列原则: 让RowKey没有规律,可以实现均匀分配。 如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。
如果没有散列字段,首字段直接是时间信息,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率. 常见的散列手段如下:
(a)加盐:
这里所说的加盐不是密码学中的加盐,而是在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。
分配的前缀种类数量应该和你想使用数据分散到不同的region的数量一致。加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点. (b)哈希:
哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据。 (c)反转:
第三种防止热点的方法时反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。
反转rowkey的例子以手机号为rowkey,可以将手机号反转后的字符串作为rowkey,这样的就避免了以手机号那样比较固定开头导致热点问题。 (d)时间戳反转:
一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,可以用Long.Max_Value - timestamp追加到key的末尾。
例如[key][reverse_timestamp] ,[key]的最新值可以通过scan [key]获得[key]的第一条记录,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。比如需要保存一个用户的操作记录,按照操作时间倒序排序,在设计rowkey的时候,可以这样设计[userId反转][Long.Max_Value - timestamp],在查询用户的所有操作记录数据的时候,直接指定反转后的userId,startRow是[userId反转][000000000000],stopRow是[userId反转][Long.Max_Value - timestamp]如果需要查询某段时间的操作记录,startRow是[user反转][Long.Max_Value - 起始时间],stopRow是[userId反转][Long.Max_Value - 结束时间]
2>.生成随机数,hash,散列值
举个例子:
原本rowKey为1001的,SHA1后变成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7
原本rowKey为3001的,SHA1后变成:49042c54de64a1e9bf0b33e00245660ef92dc7bd
原本rowKey为5001的,SHA1后变成:7b61dec07e02c188790670af43e717f0f46e8913
在做此操作之前,一般我们会选择从数据集中抽取样本,来决定什么样的rowKey来Hash后作为每个分区的临界值。
3>.字符串反转
假设有以下3个订单编号: 20200531000001 20200531000002 20200531000003 反转后: 10000013500202 20000013500202 30000013500202 如果按照上面的字符串作为RowKey则很有可能这3个订单被写入到同一个Region中,但是如果我们做一个反转操作后,很可能这3条订单数据被写入到3个不同的Region中。
4>.字符串拼接
举个例子:
20200531000001_a1b2c3
20200531000001_abcdef
四.内存优化
HBase操作过程中需要大量的内存开销,毕竟Table是可以缓存在内存中的,一般会分配整个可用内存的70%给HBase的Java堆。 但是不建议分配非常大的堆内存,因为GC过程持续太久会导致RegionServer处于长期不可用状态,一般16~48G内存就可以了,如果因为框架占用内存过高导致系统内存不足,框架一样会被系统服务拖死。 博主推荐阅读: https://www.cnblogs.com/yinzhengjie/tag/JVM/
五.HBase配置基础优化
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一般都会同一时间操作大量的文件,根据集群的数量和规模以及数据动作,设置为8192或者更高。默认值:4096。
3>.优化延迟高的数据操作的等待时间
配置文件:
hdfs-site.xml
相关参数:
dfs.image.transfer.timeout
参数说明:
如果对于某一次数据操作来讲,延迟非常高,socket需要等待更长的时间,建议把该值设置为更大的值(默认60000毫秒),以确保socket不会被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,用于指定RPC监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。
6>.优化HStore文件大小
配置文件:
hbase-site.xml
相关参数:
hbase.hregion.max.filesize
参数说明:
默认值10737418240(10GB),如果需要运行HBase的MR任务,可以减小此值,因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。
该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分为两个Hfile。
7>.优化hbase客户端缓存
配置文件:
hbase-site.xml
相关参数:
hbase.client.write.buffer
参数说明:
用于指定HBase客户端缓存,增大该值可以减少RPC调用次数,但是会消耗更多内存。一般我们需要设定一定的缓存大小,以达到减少RPC次数的目的。
8>.指定scan.next扫描HBase所获取的行数
配置文件: hbase-site.xml
相关参数: hbase.client.scanner.caching
参数说明: 用于指定scan.next方法获取的默认行数,值越大,消耗内存越大。
9>.协处理器(coprocessor)配置
配置文件: hbase-site.xml 相关参数: hbase.coprocessor.abortonerror 参数说明: 如果设置为true,则当协处理器加载失败、初始化失败或抛出意外的可丢弃对象时,将导致宿主服务器(主服务器或区域服务器)中止。
将此设置为false将允许服务器继续执行,但相关协处理器的系统范围状态将变得不一致,因为它将仅在服务器的子集中正确执行,因此这对于仅调试非常有用。
生产环境建议设置成false以增强HRegionServer的可用性。
10>.Flush、Compact、Split机制
Flush机制: 当MemStore达到阈值,将Memstore中的数据Flush进Storefile,128M就是Memstore的默认阈值。 Compact机制: compact机制则是把Flush出来的小文件合并成大的Storefile文件。 Spilt机制: split则是当Region达到阈值,会把过大的Region一分为二。 相关参数说明: 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使用内存略小于hbase.regionserver.global.memstore.lowerLimit(该值默认值大小是"hbase.regionserver.global.memstore.upperLimit"的95%)。
hbase.regionserver.optionalcacheflushinterval:3600000
内存中的文件在自动刷新之前能够存活的最长时间,默认是1H.
hbase.regionserver.region.split.policy:org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicy
region在切分的时候的默认切分策略,不同版本的切分策略是不一样的,org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicy是1.3.1版本的默认切分策略。
hbase.regionserver.regionSplitLimit:1000
当某个HRegionServer上的region到达这个限制时,不会在进行region切分,也就是一个HRegionServer默认最大允许有1000个region。
hbase.hregion.memstore.block.multiplier:4
当一个HRegion上的memstore的大小满足hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size, 这个HRegion会执行flush操作并阻塞对该HRegion的写入。
hbase.hregion.majorcompaction:604800000
一个region进行 major compaction合并的周期,在这个点的时候, 这个region下的所有hfile会进行合并,默认是7天,major compaction非常耗资源,建议生产关闭(设置为0),在应用空闲时间手动触发。
hbase.hstore.compaction.max:
每个minor compaction操作的 允许的最大hfile文件上限。
当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。问问自己,想要怎样的人生。 欢迎加入基础架构自动化运维:598432640,大数据SRE进阶之路:959042252,DevOps进阶之路:526991186