HBase优化实战

本文来自网易云社区

 

背景

Datastream一直以来在使用HBase分流日志,天天的数据量很大,日均大概在80亿条,10TB的数据。对于像Datastream这种数据量巨大、对写入要求很是高,而且没有复杂查询需求的日志系统来讲,选用HBase做为其数据存储平台,无疑是一个很是不错的选择。java

HBase是一个相对较复杂的分布式系统,并发写入的性能很是高。然而,分布式系统从结构上来说,也相对较复杂,模块繁多,各个模块之间也很容易出现一些问题,因此对像HBase这样的大型分布式系统来讲,优化系统运行,及时解决系统运行过程当中出现的问题也变得相当重要。正所谓:“你”若安好,即是晴天;“你”如有恙,我便没有星期天。apache

 

历史现状

HBase交接到咱们团队手上时,已经在线上运行有一大段时间了,期间也偶尔听到过系统不稳定的、时常会出现一些问题的言论,但咱们认为:一个能被大型互联网公司普遍采用的系统(包括Facebook,twitter,淘宝,小米等),其在性能和可用性上是毋庸置疑的,况且像Facebook这种公司,是在通过严格选型后,放弃了本身开发的Cassandra系统,用HBase取而代之。既然这样,那么,HBase的不稳定、常常出问题必定有些其余的缘由,咱们所要作的,就是找出这些HBase的不稳定因素,还HBase一个“清白”。“查案”以前,先来简单回顾一下咱们接手HBase时的现状(咱们运维着好几个HBase集群,这里主要介绍问题最多那个集群的调优):服务器

 

名称网络

数量并发

备注运维

服务器数量分布式

17oop

配置不一样,HBase、HDFS都部署在这些机器上性能

表数量测试

30+

只有部分表的数据量比较大,其余基本没多少数据

Region数量

600+

基本上都是数据量较大的表划分的region较多

请求量

50000+

服务器请求分布极其不均匀

 

应用反应常常会过段时间出现数据写入缓慢,致使应用端数据堆积现象,是否能够经过增长机器数量来解决?

  其实,那个时候,咱们自己对HBase也不是很熟悉,对HBase的了解,也仅仅在作过一些测试,了解一些性能,对内部结构,实现原理之类的基本上都不怎么清楚。因而刚开始几天,各类问题,天天晚上拉着一男一块儿摸索,顺利的时候,晚上8,9点就能够暂时搞定线上问题,更多的时候基本要到22点甚至更晚(可能那个时候流量也下去了),经过不断的摸索,慢慢了解HBase在使用上的一些限制,也就能逐渐解决这一系列过程当中发现的问题。后面挑几个相对比较重要,效果较为明显的改进点,作下简单介绍。

 

调优

首先根据目前17台机器,50000+的QPS,而且观察磁盘的I/O利用率和CPU利用率都至关低来判断:当前的请求数量根本没有达到系统的性能瓶颈,不须要新增机器来提升性能。若是不是硬件资源问题,那么性能的瓶颈到底是什么?

 

Rowkey设计问题

 

现象 

打开HBase的Web端,发现HBase下面各个RegionServer的请求数量很是不均匀,第一个想到的就是HBase的热点问题,具体到某个具体表上的请求分布以下:

HBase表请求分布

 上面是HBase下某张表的region请求分布状况,从中咱们明显能够看到,部分region的请求数量为0,而部分的请求数量能够上百万,这是一个典型的热点问题。

 

缘由

HBase出现热点问题的主要缘由无非就是rowkey设计的合理性,像上面这种问题,若是rowkey设计得很差,很容易出现,好比:用时间戳生成rowkey,因为时间戳在一段时间内都是连续的,致使在不一样的时间段,访问都集中在几个RegionServer上,从而形成热点问题。

 

解决

知道了问题的缘由,对症下药便可,联系应用修改rowkey规则,使rowkey数据随机均匀分布,效果以下:

Rowkey重定义后请求分布

 

建议

  对于HBase来讲,rowkey的范围划定了RegionServer,每一段rowkey区间对应一个RegionServer,咱们要保证每段时间内的rowkey访问都是均匀的,因此咱们在设计的时候,尽可能要以hash或者md5等开头来组织rowkey。

 

Region重分布

 

现象

HBase的集群是在不断扩展的,分布式系统的最大好处除了性能外,不停服横向扩展也是其中之一,扩展过程当中有一个问题:每次扩展的机器的配置是不同的,通常,后面新加入的机器性能会比老的机器好,可是后面加入的机器常常被分配不多的region,这样就形成了资源分布不均匀,随之而来的就是性能上的损失,以下:

HBase各个RegionServer请求

上图中咱们能够看到,每台RegionServer上的请求极为不均匀,多的好几千,少的只有几十

 

缘由

资源分配不均匀,形成部分机器压力较大,部分机器负载较低,而且部分Region过大过热,致使请求相对较集中。

 

解决

迁移部分老的RegionServer上的region到新加入的机器上,使每一个RegionServer的负载均匀。经过split切分部分较大region,均匀分布热点region到各个RegionServer上。

HBase region请求分布

 

对比先后两张截图咱们能够看到,Region总数量从1336增长到了1426,而增长的这90个region就是经过split切分大的region获得的。而对region从新分布后,整个HBase的性能有了大幅度提升。

 

建议

Region迁移的时候不能简单开启自动balance,由于balance主要的问题是不会根据表来进行balance,HBase的自动balance只会根据每一个RegionServer上的Region数量来进行balance,因此自动balance可能会形成同张表的region会被集中迁移到同一个台RegionServer上,这样就达不到分布式的效果。

基本上,新增RegionServer后的region调整,能够手工进行,尽可能使表的Region都平均分配到各个RegionServer上,另一点,新增的RegionServer机器,配置最好与前面的一致,不然资源没法更好利用。

对于过大,过热的region,能够经过切分的方法生成多个小region后均匀分布(注意:region切分会触发major compact操做,会带来较大的I/O请求,请务必在业务低峰期进行)

 

HDFS写入超时

现象

HBase写入缓慢,查看HBase日志,常常有慢日志以下:

WARN org.apache.hadoop.ipc.HBaseServer- (responseTooSlow): {"processingtimems":36096, "call":"multi(org.apache.hadoop.hbase.client.MultiAction@7884377e), rpc version=1, client version=29, methodsFingerPrint=1891768260", "client":"xxxx.xxx.xxx.xxxx:44367", "starttimems":1440239670790, "queuetimems":42081, "class":"HRegionServer", "responsesize":0, "method":"multi"}

而且伴有HDFS建立block异常以下:

INFO  org.apache.hadoop.hdfs.DFSClient - Exception in createBlockOutputStream

org.apache.hadoop.hdfs.protocol.HdfsProtoUtil.vintPrefixed(HdfsProtoUtil.java:171)

org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.createBlockOutputStream(DFSOutputStream.java:1105)

org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.nextBlockOutputStream(DFSOutputStream.java:1039)

org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:487)

通常地,HBase客户端的写入到RegionServer下某个region的memstore后就返回,除了网络外,其余都是内存操做,应该不会有长达30多秒的延迟,外加HDFS层抛出的异常,咱们怀疑极可能跟底层数据存储有关。

 

缘由

定位到多是HDFS层出现了问题,那就先从底层开始排查,发现该台机器上10块盘的空间利用率都已经达到100%。按理说,做为一个成熟的分布式文件系统,对于部分数据盘满的状况,应该有其应对措施。的确,HDFS自己能够设置数据盘预留空间,若是部分数据盘的预留空间小于该值时,HDFS会自动把数据写入到另外的空盘上面,那么咱们这个又是什么状况?

  最终经过多方面的沟通确认,发现了主要缘由:咱们这批机器,在上线前SA已经通过处理,每块盘默认预留100G空间,因此当经过df命令查看盘使用率为100%时,其实盘还有100G的预留空间,而HDFS层面咱们配置的预留空间是50G,那么问题就来了:HDFS认为盘还有100G空间,而且多于50G的预留,因此数据能够写入本地盘,可是系统层面却禁止了该写入操做,从而致使数据写入异常。

 

解决

解决的方法可让SA释放些空间出来便于数据写入。固然,最直接有效的就是把HDFS的预留空间调整至100G以上,咱们也正是这样作的,经过调整后,异常再也不出现,HBase层面的slow log也没有再出现。同时咱们也开启了HDFS层面的balance,使数据自动在各个服务器之间保持平衡。

 

建议

磁盘满了致使的问题很难预料,HDFS可能会致使部分数据写入异常,MySQL可能会出现直接宕机等等,因此最好的办法就是:不要使盘的利用率达到100%。

 

网络拓扑

 

现象

经过rowkey调整,HDFS数据balance等操做后,HBase的确稳定了许多,在很长一段时间都没有出现写入缓慢问题,总体的性能也上涨了不少。但时常会隔一段时间出现些slow log,虽然对总体的性能影响不大,但性能上的抖动仍是很明显。

 

缘由

因为该问题不常常出现,对系统的诊断带来不小的麻烦,排查了HBase层和HDFS层,几乎一无所得,由于在大多数状况下,系统的吞吐量都是正常的。经过脚本收集RegionServer所在服务器的系统资源信息,也看不出问题所在,最后怀疑到系统的物理拓扑上,HBase集群的最大特色是数据量巨大,在作一些操做时,很容易把物理机的千兆网卡都吃满,这样若是网络拓扑结构存在问题,HBase的全部机器没有部署在同一个交换机上,上层交换机的进出口流量也有可能存在瓶颈。网络测试仍是挺简单的,直接ping就能够,咱们获得如下结果:共17台机器,只有其中一台的延迟存在问题,以下:

 网络延迟测试:Ping结果

同一个局域网内的机器,延迟达到了毫秒级别,这个延迟是比较致命的,由于分布式存储系统HDFS自己对网络有要求,HDFS默认3副本存在不一样的机器上,若是其中某台机器的网络存在问题,这样就会影响到该机器上保存副本的写入,拖慢整个HDFS的写入速度。

 

解决

网络问题,联系机房解决,机房的反馈也验证了咱们的想法:因为HBase的机器后面进行了扩展,后面加入的机器有一台跟其余机器不在同一个交换机下,而这台机器正是咱们找出的有较大ping延时这台,整个HBase物理结构以下:

HBase物理拓扑结构

跟机房协调,调整机器位置,使全部的HBase机器都位于同一个交换机下,问题迎刃而解。

 

建议

  对于分布式大流量的系统,除了系统自己,物理机的部署和流量规划也至关重要,尽可能使集群中全部的机器位于相同的交换机下(有容灾需求的应用除外),集群较大,须要跨交换机部署时,也要充分考虑交换机的出口流量是否够用,网络硬件上的瓶颈诊断起来相对更为困难。

 

JVM参数调整

解决了网络上面的不稳定因素,HBase的性能又获得进一步的提升,随之也带来了另外的问题。

 

现象

  根据应用反应,HBase会阶段性出现性能降低,致使应用数据写入缓慢,形成应用端的数据堆积,这又是怎么回事?通过一系列改善后HBase的系统较之之前有了大幅度增加,怎么还会出现数据堆积的问题?为何会阶段性出现?

从上图看,HBase平均流量QPS基本能达到12w,可是每过一段时间,流量就会降低到接近零点,同时这段时间,应用会反应数据堆积。

 

缘由

  这个问题定位相对仍是比较简单,结合HBase的日志,很容易找到问题所在:

org.apache.hadoop.hbase.util.Sleeper - We slept 41662ms instead of 3000ms, this is likely due to a long garbage collecting pause and it's usually bad

经过上述日志,基本上能够断定是HBase的某台RegionServer出现GC问题,致使了服务在很长一段时间内禁止访问。

  HBase经过一系列的调整后,整个系统的吞吐量增长了好几倍,然而JVM的堆大小没有进行相应的调整,整个系统的内存需求变大,而虚拟机又来不及回收,最终致使出现Full GC

 

解决

   GC问题致使HBase整个系统的请求降低,经过适当调整JVM参数的方式,解决HBase RegionServer的GC问题。

 

建议

  对于HBase来讲,自己不存在单点故障,即便宕掉1,2台RegionServer,也只是使剩下几台的压力有所增长,不会致使整个集群服务能力降低不少。可是,若是其中某台RegionServer出现Full GC问题,那么这台机器上全部的访问都会被挂起,客户端请求通常都是batch发送的,rowkey的随机分布致使部分请求会落到该台RegionServer上,这样该客户端的请求就会被阻塞,致使客户端没法正常写数据到HBase。因此,对于HBase来讲,宕机并不可怕,但长时间的Full GC是比较致命的,配置JVM参数的时候,尽可能要考虑避免Full GC的出现。

 

后记

 通过前面一系列的优化,目前Datastream的这套HBase线上环境已经至关稳定,连续运行几个月都没有任何HBase层面因为系统性能不稳定致使的报警,平均性能在各个时间段都比较稳定,没有出现过大幅度的波动或者服务不可用等现象。

本文来自网易云社区,经做者蒋鸿翔受权发布。

相关文章
相关标签/搜索