如何防止 Hbase 一次写入数据过多导致的各种问题(建表预分区、集群 regionserver 优化)

目录

表级

根据 rowkey 的规则进行建表预分区

集群级

首先我们简单回顾下整个写入流程

当写入过快时会遇见什么问题?

如何避免RS OOM?


表级

根据 rowkey 的规则进行建表预分区

详情见:使用 Hbase Shell 命令创建预分区表(hbase预分区)

集群级

首先我们简单回顾下整个写入流程

client api ==> RPC ==>  server IPC ==> RPC queue ==> RPC handler ==> write WAL ==> write memstore ==> flush to  filesystem

整个写入流程从客户端调用API开始,数据会通过 protobuf 编码成一个请求,通过 scoket 实现的 IPC 模块被送达 server 的 RPC 队列中。最后由负责处理 RPC 的 handler 取出请求完成写入操作。写入会先写 WAL 文件,然后再写一份到内存中,也就是 memstore 模块,当满足条件时,memstore 才会被 flush 到底层文件系统,形成 HFile。

当写入过快时会遇见什么问题?

写入过快时,memstore 的水位会马上被推高。
你可能会看到以下类似日志:

RegionTooBusyException: Above memstore limit, regionName=xxxxx ...

这个是 Region 的 memstore 占用内存大小超过正常的4倍,这时候会抛异常,写入请求会被拒绝,客户端开始重试请求。当达到128M的时候会触发 flush memstore,当达到128M * 4还没法触发 flush 时候会抛异常来拒绝写入。两个相关参数的默认值如下:

hbase.hregion.memstore.flush.size=128M
hbase.hregion.memstore.block.multiplier=4

或者这样的日志:

regionserver.MemStoreFlusher: Blocking updates on hbase.example.host.com,16020,1522286703886: the global memstore size 1.3 G is >= than blocking 1.3 G size
regionserver.MemStoreFlusher: Memstore is above high water mark and block 528ms

这是所有 region 的 memstore 内存总和开销超过配置上限,默认是配置 heap 的40%,这会导致写入被阻塞。目的是等待 flush 的线程把内存里的数据 flush 下去,否则继续允许写入 memestore 会把内存写爆

hbase.regionserver.global.memstore.upperLimit=0.4  # 较旧版本,新版本兼容
hbase.regionserver.global.memstore.size=0.4 # 新版本

当写入被阻塞,队列会开始积压,如果运气不好最后会导致 OOM,你可能会发现 JVM 由于 OOM crash 或者看到如下类似日志:

ipc.RpcServer: /192.168.x.x:16020 is unable to read call parameter from client 10.47.x.x
java.lang.OutOfMemoryError: Java heap space

HBase 这里我认为有个很不好的设计,捕获了 OOM 异常却没有终止进程。这时候进程可能已经没法正常运行下去了,你还会在日志里发现很多其它线程也抛 OOM 异常。比如 stop 可能根本 stop不 了,RS 可能会处于一种僵死状态。

如何避免RS OOM?

加快 flush 速度

hbase.hstore.blockingWaitTime = 90000 ms
hbase.hstore.flusher.count = 2
hbase.hstore.blockingStoreFiles = 10

当达到 hbase.hstore.blockingStoreFiles 配置上限时,会导致 flush 阻塞等到 compaction 工作完成。阻塞时间是 hbase.hstore.blockingWaitTime,可以改小这个时间。hbase.hstore.flusher.count 可以根据机器型号去配置,可惜这个数量不会根据写压力去动态调整,配多了,非导入数据多场景也没用,改配置还得重启。

同样的道理,如果 flush 加快,意味这 compaction 也要跟上,不然文件会越来越多,这样 scan 性能会下降,开销也会增大。

hbase.regionserver.thread.compaction.small = 1
hbase.regionserver.thread.compaction.large = 1

增加 compaction 线程会增加 CPU 和带宽开销,可能会影响正常的请求。如果不是导入数据,一般而言是够了。好在这个配置在云 HBase 内是可以动态调整的,不需要重启。

上述配置都需要人工干预,如果干预不及时 server 可能已经 OOM 了,这时候有没有更好的控制方法?

hbase.ipc.server.max.callqueue.size = 1024 * 1024 * 1024 # 1G

直接限制队列堆积的大小。当堆积到一定程度后,事实上后面的请求等不到 server 端处理完,可能客户端先超时了。并且一直堆积下去会导致 OOM,1G的默认配置需要相对大内存的型号。当达到 queue 上限,客户端会收到 CallQueueTooBigException  然后自动重试。通过这个可以防止写入过快时候把 server 端写爆,有一定反压作用。线上使用这个在一些小型号稳定性控制上效果不错。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值