HBase写入过快性能分析及调优

导读:本篇文章讲解 HBase写入过快性能分析及调优,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

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。


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

HBase会检查Memstore的大小,如果Memstore超过设定的blockingMemStoreSize则触发flush的操作,并抛出RegionTooBusyException,阻塞写操作的进行。如下源码所示:

  private void checkResources()

    throws RegionTooBusyException {

    // If catalog region, do not impose resource constraints or block updates.

    // 如果是Meta Region,不实施资源约束或阻塞更新

    if (this.getRegionInfo().isMetaRegion()) return;

    // 如果Region当前内存大小超过阈值

    // 这个memstoreSize是当前时刻HRegion上MemStore的大小,它是在Put、Append等操作中调用addAndGetGlobalMemstoreSize()方法实时更新的。

    // 而blockingMemStoreSize是HRegion上设定的MemStore的一个阈值,当MemStore的大小超过这个阈值时,将会阻塞数据更新操作

if (this.memstoreSize.get() > this.blockingMemStoreSize) {

      // 更新阻塞请求计数器

      blockedRequestsCount.increment();

      // 请求刷新Region

requestFlush();

 

      // 抛出RegionTooBusyException异常

      throw new RegionTooBusyException(“Above memstore limit, ” +

          “regionName=” + (this.getRegionInfo() == null ? “unknown” :

          this.getRegionInfo().getRegionNameAsString()) +

          “, server=” + (this.getRegionServerServices() == null ? “unknown” :

          this.getRegionServerServices().getServerName()) +

          “, memstoreSize=” + memstoreSize.get() +

          “, blockingMemStoreSize=” + blockingMemStoreSize);

    }

  }

blockingMemStoreSize的大小由hbase.hregion.memstore.flush.size和hbase.hregion.memstore.block.multiplier共同作用,等于两者相乘,我们的hbase.hregion.memstore.flush.size设置的是256M,hbase.hregion.memstore.block.multiplier设置的是3,因此:blockingMemStoreSize=805306368。具体的blockingMemStoreSize计算的代码如下:

    this.blockingMemStoreSize = this.memstoreFlushSize *

  conf.getLong(HConstants.HREGION_MEMSTORE_BLOCK_MULTIPLIER,

    HConstants.DEFAULT_HREGION_MEMSTORE_BLOCK_MULTIPLIER);

写入过快时,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 # 新版本

当写入请求由于达到memstore上限而被阻塞,队列会开始积压,如果运气不好最后会导致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端写爆,有一定反压作用。线上使用这个在一些小型号稳定性控制上效果不错。

更多参照:

https://linux.cn/thread-17641-1-1.html

https://www.cnblogs.com/quchunhui/p/7561972.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/14045.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!