HBASE 系列 一个RegionServer的Region数量多少合适?

HBASE 系列 一个RegionServer的Region数量多少合适?,第1张

HBase 官方文档说一个RegionServer被设计跑20 200个regions,数据大小约5 50Gb。

但是,建议regions在100个左右。

首先 ,理解一个概念『MSLAB』,即MemStore-Local Allocation Buffer。

每个store都有一个memstore,为了避免在大量数据写入,堆中产生很多碎片,导致stop-the-world GC出现,设置hbase.hregion.memstore.mslab.enabled,来预防此问题。即本地MemStore允许分配的内存大小。

当一个HRegion中的所有MemStore的大小总和超过了hbase.hregion.memstore.flush.size的大小,默认128MB。此时当前的HRegion中所有的MemStore会Flush到HDFS中。

当全局MemStore的大小超过了hbase.regionserver.global.memstore.upperLimit的大小,默认40%的内存使用量。此时当前HRegionServer中所有HRegion中的MemStore都会Flush到HDFS中,Flush顺序是MemStore大小的倒序,直到总体的MemStore使用量低于hbase.regionserver.global.memstore.lowerLimit,默认38%的内存使用量。

.

1. 对表做预分区处理(即在建表时指定Region数量和拆分边界);

2.配置hbase.hregion.max.filesize为50GB

以fileServer为例,在使用默认的split策略--IncreasingToUpperBoundRegionSplitPolicy 的情况下,16个预分区Region, 则单个Resion容量达到 min(32,50),即32GB时分裂。

3.修改Linux最大文件句柄数

因为hbase是以文件的形式存储数据,最大文件句柄数影响着hbase的并发量。

用root权限修改/etc/security/limits.conf文件,增加以下内容(前面的*不能忽略):

*              soft    nproc          10240

*              hard    nproc          10240

*              soft    nofile          10240

*              hard    nofile          10240 

编辑/etc/pam.d/common-session,加入一行

session required  pam_limits.so

编辑/etc/profile,加入

ulimit -SHn 51200

重新登陆,生效

4.HRegionServer挂掉异常和解决:

is not online on......

常规解决方案:

  删除zk中hbase的缓存

  重启hbase

使用上述解决方案后本次异常依旧存在,并且HMaster和HRegionServer都不断的自动挂掉。

HMaster报错:

解决方案:

新增配置(看情况决定使用不使用,建议在HMaster不能启动时排除错误使用)(让启动hbase时只让HMaster去进行日志split,缺点是恢复数据时候速度慢):

<property>

<name>hbase.master.distributed.log.splitting</name>

<value>false</value>

</property>

   删除WAL文件(会丢数据):

6. RPC请求的最大线程数

hbase.regionserver.handler.count  默认是10,在服务器测试时建议设置到50(经测试在单个Region Server时无用,单个RegionServer 最多在6个线程put时保持稳定)

7.日志分割(hbase出错后恢复数据)

MemStore中大量更新丢失时,对数据进行恢复时会做日志分割

hbase.regionserver.hlog.splitlog.writer.threads 日志分割的线程数, 默认为3 ,建议设定为10

8.Region Server频繁掉线

出现Hbase Region Server频繁掉线的情况,表现为在多线程put的情况下,忽然Hbase Region Server掉线

猜测是GC或者split过程中没有及时和ZK通信,导致与ZK连接时间超时,zk返回dead region到master,当Hbase Region恢复正常后,找不到wal,产生如下报错。

zookeeper.session.timeout :默认值是3分钟

但是 hbase regionserver和zookeeper的timeout不是单方面决定的,是取决于hbase的zookeeper.session.timeout和zookeeper的MaxSessionTimeout中的最小值

配置hbase:

zookeeper.session.timeout

600000

配置zookeeper:

tickTime=30000

9.内存及GC优化

在测试的过程中依旧出现Hbase Region Server掉线的情况,报错如下

2021-02-0318:49:14,091INFO[sync.0]wal.FSHLog: Slow sync cost:1955ms, current pipeline: []

2021-02-0318:49:14,091WARN[regionserver/botsc/192.168.0.107:16020.append-pool5-t1]wal.MetricsWAL: regionserver/botsc/192.168.0.107:16020.append-pool5-t1 took1953ms appending an edit to wal len~=109

2021-02-0318:49:14,106ERROR[sync.3]wal.FSHLog:Errorsyncing, request close of WAL

java.io .IOException:io.grpc.StatusRuntimeException: CANCELLED: Failed to stream message

    at seaweed.hdfs.SeaweedOutputStream.flushWrittenBytesToServiceInternal(SeaweedOutputStream.java:78)

    at seaweed.hdfs.SeaweedOutputStream.flushWrittenBytesToServiceAsync(SeaweedOutputStream.java:263)

    at seaweed.hdfs.SeaweedOutputStream.flushInternalAsync(SeaweedOutputStream.java:243)

    at seaweed.hdfs.SeaweedOutputStream.flush(SeaweedOutputStream.java:129)

at java.io .FilterOutputStream.flush(FilterOutputStream.java:140)

at java.io .DataOutputStream.flush(DataOutputStream.java:123)

    at org.apache.hadoop.hbase.regionserver.wal.ProtobufLogWriter.sync(ProtobufLogWriter.java:170)

    at org.apache.hadoop.hbase.regionserver.wal.FSHLog$SyncRunner.run(FSHLog.java:1286)

    at java.lang.Thread.run(Thread.java:748)

修改hbase的配置文件hbase-env.sh,GC优化如下:

export HBASE_HEAPSIZE=21384

export master_heapsize=8292

export regionserver_heapsize=21384

export HBASE_OPTS="$HBASE_OPTS -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=60 -XX:+UseParNewGC -XX:ParallelGCThreads=6"

export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS $HBASE_JMX_BASE -Xmx8g -Xms8g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70"

export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS $HBASE_JMX_BASE -Xmx20g -Xms20g -Xmn1g -XX:+UseParNewGC

-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70"

[toc]

随着集群中总的Region数持续增长,每个节点平均管理的Region数已达550左右,某些大表的写入流量一上来,Region Server就会不堪重负,相继挂掉。

在HBase中,Region的一个列族对应一个MemStore,通常一个MemStore的默认大小为128MB(我们设置的为256MB),见参数 hbase.hregion.memstore.flush.size 。当可用内存足够时,每个MemStore可以分配128MB的空间。

当表的写入流量上升时,假设每个Region的写入压力相同,则理论上每个MemStore会平均分配可用的内存空间。

因此,节点中Region过多时,每个MemStore分到的内存空间就会变小。此时,写入很小的数据量,就会被强制flush到磁盘,进而导致频繁刷写,会对集群HBase与HDFS造成很大的压力。

同时,Region过多导致的频繁刷写,又会在磁盘上产生非常多的HFile小文件,当小文件过多的时候,HBase为了优化查询性能就会做Compaction操作,合并HFile,减少文件数量。当小文件一直很多的时候,就会出现 “压缩风暴”。Compaction非常消耗系统的IO资源,还会降低数据的写入速度,严重时会影响正常业务的进行。

关于每个Region Server节点中,Region数量大致合理的范围,HBase官网上也给出了定义:

可见,通常情况下,每个节点拥有20-200个Region是比较正常的。

其实,每个Region Server的最大Region数量由总的MemStore内存大小决定。每个Region的每个列族会对应一个MemStore,假设HBase表都有一个列族,那么每个Region只包含一个MemStore。一个MemStore大小通常在128~256MB,见参数: hbase.hregion.memstore.flush.size 。默认情况下,RegionServer会将自身堆内存的40%(我们线上60%)(见参数: hbase.regionserver.global.memstore.size )提供给节点上的所有MemStore使用,如果所有MemStore的总大小达到该配置大小,新的更新将会被阻塞并且会强制刷写磁盘。因此,每个节点最理想的Region数量应该由以下公式计算(假设HBase表都有统一的列族配置):

((RS memory) * (total memstore fraction)) / ((memstore size)*(column families))

其中:

以我们线上集群的配置举例,我们每个RegionServer的堆内存是32GB,那么节点上最理想的Region数量应该是: 32768*0.6/256 ≈ 76 (32768*0.6/128 ≈ 153)

上述最理想的情况是假设每个Region上的填充率都一样,包括数据写入的频次、写入数据的大小,但实际上每个Region的负载各不相同,有的Region可能特别活跃、负载特别高,有的Region则比较空闲。所以,通常我们认为2 3倍的理想Region数量也是比较合理的,针对上面举例来说,大概200 300个Region左右算是合理的。

针对上文所述的Region数过多的隐患,以下内容主要从两方面考虑来优化。

提高内存的目的是为了增加每个Region拥有的MemStore的空间,避免其写入压力上升时,MemStore频繁刷写,形成小的HFile过多,引起压缩风暴,占用大量IO。

但其实RS的堆内存并不是越大越好,我们开始使用HBase的时候,对CMS和G1相关的参数,进行了大量压测,测试指标数据表明,内存分配的越大,吞吐量和p99读写平均延时会有一定程度的变差(也有可能是我们的JVM相关参数,当时调配的不合理)。

在我们为集群集成jdk15,设置为ZGC之后,多次压测并分析JVM日志之后,得出结论,在牺牲一定吞吐量的基础上,集群的GC表现能力确实提升的较为明显,尤其是GC的平均停顿时间,99.9%能维持在10ms以下。

而且ZGC号称管理上T的大内存,停顿时间控制在10ms之内(JDK16把GC停顿时间控制在1ms内,期待JDK17 LTS),STW时间不会因为堆的变大而变长。

因此理论上,增加RS堆内存之后,GC一样不会成为瓶颈。

之所以考虑在单节点上部署多个Region Server的进程,是因为我们单个物理机的资源配置很高,内存充足(三百多G,RS堆内存只分了32G)、而HBase又是弱计算类型的服务,平时CPU的利用率低的可怜,网络方面亦未见瓶颈,唯一掉链子的也就属磁盘了,未上SSD,IO延迟较为严重。

当然,也曾考虑过虚拟机的方案,但之前YCSB压测的数据都不太理想;K8s的调研又是起步都不算,没有技术积累。因此,简单、直接、易操作的方案就是多RS部署了。

以下内容先叙述CDH中多RS进程部署的一些关键流程,后续将在多RS、单RS、单RS大堆环境中,对集群进行基准性能测试,并对比试验数据,分析上述两种优化方案的优劣。

我们使用的HBase版本是 2.1.0-cdh6.3.2 ,非商业版,未上Kerberos,CDH中HBase相关的jar包已替换为用JDK15编译的jar。

多Region Server的部署比较简单,最关键的是修改 hbase-site.xml 中region server的相关端口,避免端口冲突即可。可操作流程如下。

修改所需配置文件

hbase-site.xml 配置文件一定不要直接从 /etc/hbase/conf 中获取,这里的配置文件是给客户端用的。CDH管理的HBase,配置文件都是运行时加载的,所以,找到HBase最新启动时创建的进程相关的目录,即可获取到服务端最新的配置文件,如:/var/run/cloudera-scm-agent/process/5347-hbase-REGIONSERVER。需要准备的目录结构如下:

不需要HBase完整安装包中的内容(在自编译的完整安装包中运行RS进程时,依赖冲突或其他莫名其妙的报错会折磨的你抓狂),只需要bin、conf目录即可,pids文件夹是自定义的,RS进程对应pid文件的输出目录,start_rs.sh、stop_rs.sh是自定义的RS进程的启动和关闭脚本。

重点修改下图标注的配置文件,

还有日志文件名的一些输出细节,可以按需在 bin/hbase-daemon.sh 中修改。

运行或关闭RS进程

中间有异常,请查看相关日志输出。

集群Region数疯涨,当写入存在压力时,会导致RS节点异常退出。为了解决目前的这种窘境,本次优化主要从单节点多Region Server部署和提高单个Region Server节点的堆内存两方面着手。

那这两种优化方案对HBase的读写性能指标,又会产生什么样的影响呢?我们以YCSB基准测试的结果指标数据做为参考,大致评价下这两种应急方案的优劣。

用于此次测试的HBase集群的配置

此次测试使用的数据集大小

测试方法

压测时选择的读写负载尽量模拟线上的读写场景,分别为:读写3/7、读写7/3、读写5/5;

压测时唯一的变量条件是:多RS部署(32G堆,在每个节点上启动3个RS进程,相当于集群中一共有15个RS节点)、单RS部署(32G小堆)和单RS部署(100G大堆),并尽可能保证其他实验条件不变,每个YCSB的工作负载各自运行20分钟左右,并且重复完整地运行5次,两次运行之间没有重新启动,以测量YCSB的吞吐量等指标,收集的测试结果数据是5次运行中最后3次运行的平均值,为了避免第一轮和第二轮的偶然性,忽略了前两次的测试。

YCSB压测的命令是:

收集实验数据后,大致得出不同读写负载场景下、各个实验条件下的指标数据,如下图。

上述的测试数据比较粗糙,但大致也能得出些结论,提供一定程度上的参考。

多RS进程部署的模式,起到了一定程度上的进程间资源隔离的作用,分担了原先单台RS管理Region的压力,最大化利用了物理机的资源,但多出来的一些Region Server,需要单独的管理脚本和监控系统来维护,增加了维护成本。多个RS依赖同一台物理机,物理节点宕机便会影响多个RS进程,同时,某一个Region Server出现热点,压力过大,资源消耗过度,也许会引起同机其他进程的不良,在一定程度上,牺牲了稳定性和可靠性。

增加单个RS进程的堆内存,MemStore在一定程度上会被分配更充裕的内存空间,减小了flush的频次,势必会削弱写入的压力,但也可能会增加GC的负担,我们或许需要调整出合适的GC参数,甚至需要调优HBase本身的一些核心参数,才能兼顾稳定和性能。然而,这就又是一件漫长而繁琐的事情了,在此不过分探讨。

面对性能瓶颈的出现,我们不能盲目地扩充机器,在应急方案采取之后,我们需要做一些额外的、大量的优化工作,这或许才是上上之策。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/520214.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-06-21
下一篇2023-06-21

发表评论

登录后才能评论

评论列表(0条)

    保存