HBase in Practice:性能、监控及问题解决
大数据、算法的交流学习平台 圈内人都在关注
本文根据阿里巴巴高级技术专家李钰(Yu Li)老师在中国HBase技术社区第二届MeetUp:“HBase技术解析及应用实践”中分享的《HBase in Practice-性能、监控及问题解决》编辑整理而成,在未改变原意的基础上稍做整理。
李钰(Yu Li)老师
今天分享主要从两个大的部分介绍,第一部分会讲一些性能优化的知识,针对IO的性能优化,不同版本值得注意的性能问题/优化;第二部分将监控应该关注哪些指标以及在日志里面如何做问题排查。
首先讲一下针对IO性能优化。每个厂商IO硬件性能都不一样,在云上应用HBase也有很多不同的硬盘类型可以选择。针对不同的硬件,需要利用的功能和注意的问题也不一样。如HDD,它的IO能力比较弱,很容易打爆。在HDD架设HBase要避免磁盘被打爆,HBase提供了很多方法,第一个就是Compaction限流,基本思想就是限制它每秒能写出的数据量,在1.1.0版本以上才能使用,对于1.3.0版本分界线以上以下配置不同,具体配置如上图所示。你可以设置其吞吐 的上限和下限,也可以设置平峰期的限制。我们进行限流肯定一般是在高峰期,在平峰期没有必要,也或者平峰期你有没有其他的应用,有时也会跑一些其他的应用,如spark等。Flush限流是在1.3.0版本以上支持的,其实主要的IO来源就是Compaction和Flush,配置与Compaction比较像。值得注意的是限流不能过低,如果过低Compaction的HFile数就降不下来,blockStoreFiles默认值是20,如果超过20,flush就会delay,内存会膨胀,如果膨胀超过一定区域就会blocking update,会出现写入延迟阻塞。因此两者限流需要依据实际限流,不能限流过低。
另外一个在HDD上比较适合是Per-CF Flush,在1.1.0版本以上就支持,默认配置是flush all stores,当main Store的大小达到设定阀值,就会将所有的CF都flush出来。但是有些CF文件比较小,会出现浪费io,另外刷出很多小文件需要compaction,对磁盘也会有影响。因此出现了Per-CF Flush,在1.1.0版本以上可以用,从1.1.0-2.0实质是设置了一个下限,如果CF文件在main Store时超过16M就将其flush,没有超过就不flush。后续在社区基础上做了改变,将默认值改为flush大小除以CF的个数,这样的问题有可能出现CF过多,因此也会有下限值控制,也是16M。使用这个功能也需要注意,开启这个功能有很多数据是不flush,但是如果出现故障,replay的数据会变多,在HBase中有个参数optionalcacheflushinterval,可以设置过多长时间强制flush一次,还有一个flush prechanges,就是有多少change就flush一次;一个默认值是1小时,后面是3千万。
第三个方案是多盘,多盘在社区1.0版本就有多log的功能。如果在自己的机器上,服务器都是12块硬盘,如果用一个WAL(writeahead log),HDFS是三个副本,虽然能将吞吐打满,三个副本需要三个盘,无法使用完,IO能力没充分利用。解决方式就是用多个WAL,一个region server配置4个WAL,测试性能会提升20%。版本低于1.2.0:replication存在问题, hbase.wal.provider->multiwall,hbase.wal.regiongrouping.strategy-> bounded,根据盘数设置hbase.wal.regiongrouping.numgroups。需要注意写多少WAL是依据你的盘确定,IO能力是否充足。
SSD在HBase里面也有很好的支持,SSD对性能的优化分为两个部分,一方面是读,另一方面是写。影响写的性能就是WAL的写,SSD能很大的降低其响应时间,在用SSD时也可以用Multi WAL,其写入性能比单WAL提升40%以上。从读方面来说,在CF可以设置Storage Policy,但该功能在2.0版本上才有。对不同的CF设置不同的Storage Policy(ONE_SSD,ALL_SSD),设置多CF的原因是数据的冷热程度是不一样的。Bulkload也需要支持Storage Policy配置,如果生成的文件都是HDD,会影响读取的性能。
需要注意的是如果使用ONE_SSD策略需要允许HDFS client优先读远程SSD上的副本,但是未合入社区版本,需要手动backport。对于混合磁盘环境(既有SSD又有HDD),WAL策略可以是ONE_SSD,对CF级别也可以是ONE_SSD。值得注意的是SSD也需要开启限流。
不同版本有一些尤其值得注意的性能问题。比如Merge MVCC and SequenceId引发的性能问题:branch-1.0不要使用1.0.3以下版本,branch-1.1不要使用1.1.3以下版本。高负载下写入性能瓶颈: 如果线上发现大量handlerwait在WALKey#get Write Entry,建议升级到1.4.0以上版本,对ASYNC_WAL写入性能提升尤其明显 。在读性能方面,如果用的是Bucket Cache,在高并发读取单key时存在性能问题,在1.2.0以上版本可以解决。如果远程读SSD,需要考虑网络开销,ONE_SSD策略+HDFS远程读开销尤其大。
接下来讲一下问题排查,首先是RPC相关监控:Server响应时间,Server处理时间,请求排队时间。Total Call Time记录的是请求到达你的RegionServer开始到server请求完结束,不包含发送结果的时间。如果业务端发现HBase请求延迟但是server端延迟相关监控数据看起来没问题,这种情况需要业务debug客户端的问题,例如是否业务程序GC,或者客户端是不是网络出口存在拥塞。Total Call Time等于ProcessCall Time加上QueueCall Time,请求到达server是先进入一个队列,如果handler不繁忙,QueueCall Time会很短,但是如果server很繁忙active handler数很满,QueueCallTime会很长,请求是从队列出来后处理。Active Handler在1.4.0版本以前是没有读写分离监控的。读写分离的好处就是Handler打满到底是读出问题还是写出问题就可以很容易监控。RPC队列长度也可以判断机器是否出问题了,RPC连接数很高也是消耗系统资源。上图是我们监控指标图,通过毛刺就可以推测哪台机器可能存在问题。
请求相关指标对debug很重要,Put请求latency,Get请求latency,Scan请求latency等这些都会监控。需要说明的是对latency的监控,HBase出问题到底是文件系统出问题了还是RegionServer出问题了应该是个常见问题,因为底层会有一个文件系统,文件系统故障的话HBase肯定会受影响,因次对于put来说要监控WAL sync latency,对于get要监控HDFS pread latency,Scan请求监控HDFS readlatency。对于HDFS pread/read latency的监控指标需要1.4.0版本以上才有。如果发现Get请求latency很高,HDFS pread latency也很高,那么基本确定是HDFS毛刺问题。否则就必须对p999高的RegionServer一一排查。
第三个就是内存相关的指标,GC相关的监控指标对于排查问题作用未必很大(是否存在GC问题更多的是查GC日志更有效果),但是可以监控整体情况。Pause Time Without GC不是进程GC导致的问题时,在1.4.0版本以上会发现一些日志的,这个时候需要关注一些系统的指标,比如内存整理有可能导致整个系统hang住,或者资源瓶颈,比如CPU打满等,都会导致进程堵塞。再一个就是对Block Cache/MemStore Size的监控,如何监控Hfile数过多,一方面可以监控blocking update的频率,另一方面是看MemStoreSize是否变大了。Block Cache在1.3.0版本以上可以区分data和meta命中率,meta block命中率一般都很高,访问频率也很高,如果不区分开meta和data,cache命中率有可能是假的。比如从我们线上的观察来看,真实的data block命中率在65%,但是meta命中率基本是100%。
如果看到一个regionserver handler打满了,需要看regionServer单机指标。如region大小,这个指标引起cache的命中率,get和写操作数,看topN哪些请求非常高,handler打满,get时间非常高,可以查询嘛个region访问过多,有些情况是访问值超过正常值导致的,因此可以通过表找到问题去解决。再一个就是compaction队列长度和flush队列长度。
如何发现stale的Region Server,如果出现坏盘,请求卡在IO上一直无法返回,响应时间相关指标无法捕捉,在total call time中无法体现。还有就是你的p999数值很好但是机器已经出问题,因为出问题的请求没有汇报给server,另外如果机器资源耗尽,新的请求无法连接server,从响应时间等server metrics上也体现不出来。因此我们做了一个增强health check,定期向自己发请求并设置超时时间,失败超过一定概率报警。这个功能暂时还没有贡献回社区,处于in progress状态,后续会完成。其实会出现一个情况就是系统资源耗尽,但是已经启动的线程可以运行,但是无法启动新的线程,就是一台机器已经不能服务,但是master还是可以服务。
接下来讲一下日志的排查,首先关于慢请求。如发现一个server的999时间很长,第一反应是登陆该台RegionServer查看日志,尤其是responseTooSlow日志,但是老版本是不会打印任何有关processingtime、row等具体信息的,因此请关注HBASE-16033/HBASE-16972这两个JIRA。会打印详细信息,前面一个截图是对普通请求,后面一个截图是对scan。经常会看到scan超时等这些信息都是很重要的。branch-1.1要求1.1.8以上,branch-1.2要求1.2.5以上,或1.3.0以上版本。在自己的版本还做了一些事情,但是暂时没有Upstream到社区,比如对于慢请求,如何区分是long process time还是longqueueTime,因为一个long process time会导致一系列的longqueueTime。如果不区分会看到很多responseTooSlow,但是你并不知道出现的问题是什么。当然还需要设置阈值,超过多长时间才算慢请求,我们是超过10秒才算慢请求,这个可以自己配置。那如果请求处理时间很接近但未到达10秒,比如8秒,对于这种慢请求怎么debug?这时需要去region Server上截取jstack,去查看handler线程wait在什么地方,wait的地方出现了多少。
在Client端也有些日志也是非常重要的,大部分版本对于single请求打印都很全,但是要注意batch。列出的JIRA(branch-1.1要求1.1.6以上,branch-1.2要求1.2.3以上,或1.3.0以上版本)会在有慢请求时,去打印具体是哪个region,还有目前运行在哪个server上,或者在batch请求异常时打印异常的batch栈。客户端还有其他一些很好的机制,比如hbase客户端可以配置backoff policy,就是通过RegionServer的region load判断是否需要sleep一段时间,这样在server繁忙期间不会发送大量的请导致情况恶化。
后续有机会可以讨论如何排查GC、内存泄漏等复杂问题,如何定位疯狂访问RS的问题客户端应用,如何规避HDFS故障对HBase的影响,2.0黑科技在线上应用可能踩的坑,升级HBase版本有哪些必须的准备以及线上升级操作有哪些注意事项。
——END