HBase优化 | RegionServer从17台优化到10台总结(一)

 

本文是前几篇文章的小结,介绍如何通过技术手段,挖掘HBase服务的潜力,将分组的服务器数从17台降低到10台。

 

确定优化目标
沟通交流后,业务方更看重降低成本。数据量梳理后略有降低,保证吞吐,无长期请求堆积前提下可以放宽延时要求。为了更快的进行优化,放宽稳定性可以要求接受短期波动。
另外,该分组的RegionServer之前存在不稳定的问题,这次优化也一并解决。

系统资源瓶颈和优化效果
降低成本,即省机器,就是用更少的服务器满足业务需求。需要搞清楚单台服务器的瓶颈在哪。下面分析单台服务器的指标和优化效果。

 

CPU利用率
因为HBase是重IO,轻计算的服务,一般来说HBase服务CPU利用率较低。优化前单台CPU利用率平均在5%,峰值在10%左右。直接机器减半也没有压力。
空闲的CPU利用率,可以用来置换更高的存储压缩比,节约存储空间。更多的业务线程和GC线程,提高吞吐能力,减少GC对系统吞吐和延时毛刺的影响。
峰值CPU在40%以下,说明CPU资源充足富裕,可以减机器,用CPU换存储空间,提高业务吞吐。

内存使用
256GB内存,datanode 4g,RegionServer堆内50g,堆外100g,空闲大概100g。可以提高单机RegionServer内存到堆内100g,堆外120g,留10%的空闲。
提高内存的好处很多。单机负载不变的前提下,增加堆内内存,可以降低GC频率减少毛刺出现频率,降低GC时间占比提高吞吐(另外如果Mixed GC周期能超过大多数Region Flush的周期,回收会更有效率)。增加MemStore写缓存,可以降低写放大效应,从而降低网络和磁盘IO。降低写放大,还可以减少Compact,提高缓存有效性从而增加缓存命中率,进一步降低读IO,减少读请求延时。增加堆外内存,可以缓存命中率。
举个例子,一台服务器提高内存使用量,同时Region数变为其他服务器的2倍。堆外内存增加20%而Region数翻倍,单纯数字上来看缓存命令率应该下降,实际稳定后命中率保持在96%高于其他服务器的94%,这就是降低Compact提高命中率的收益。
增大内存的坏处是,单次GC时间会更长,极端情况下请求延时的毛刺会更明显。另外一些HBase内部的数据结构,如MemStore的ConcurrentSkipListMap,对象数太多性能会下降的很厉害,需要结合用户需求,在Region数,hbase-site参数,GC参数上综合考虑,做一个权衡。

网络IO
网络In 20MB,Out 40到100MB波动。万兆网卡峰值也就百MB以内,机器数砍半没压力。

磁盘IO
非Major Compact时段,磁盘读流量较高,高峰期200MB到300MB,主要来自Compact。写流量50MB/s。磁盘流量较高是个瓶颈,需要技术优化。
磁盘读流量主要是本地RegionServer业务读和Compact读,写流量主要是本地RegionServer写wal,flush,compact,以及其他datanode的写副本。
网络in主要是业务写入请求和其他datanode写副本请求,网络out主要是业务查询响应和RegionServer写WAL,Flush,Compact写其他datanode副本的请求。
由于业务查询主要走内存缓存(95%),HFile又有很高的压缩比(1:5左右),如果不考虑服务端filter过滤的情况,业务读引起的磁盘IO应该只是网络查询响应IO的百分之一。
用户的业务场景没用filter,所以可以推论读IO主要来自Compact ,验证了写放大效应明显。
经过参数优化降低写放大效应,Region数不变,单机磁盘读IO下降到之前的1/3,80MB左右。
又经过Region合并,参数继续优化,单机两倍Region负载,读IO保持在150MB到200MB之间,比之前单倍Region负载还要低很多。

存储量
集群存储峰值大概有三个时间点,每周Major Compact前,每周Major Compact后,Major Compact中(大概是major compact前存储*(1+并发major region数/总Region数))。
目前没有明确用哪个存储量衡量峰值,一般定期检查,发现用到差不多了就和用户沟通加机器。不允许独立分组存储总量大于分组机器所提供的存储总量。
在Major Compact前取了数据的总量,刚好跟10台的存储量差不多,可以降低到10台。

稳定性
如系列文章上一篇GC执行细节和参数调优方法论详所说,分组之前存在稳定性的问题。出现问题时需要人工操作迁移Region,重启。当机器数减到17台,直接减机器立刻加剧了问题出现的频率。经分析,问题主要出在GC参数上,详见上一篇文章。

综述
通过瓶颈分析,解决了磁盘IO问题后,10台服务器是存储量瓶颈,所以第一步的目标是降到10台。

优化细节
合并Region

之前分组17台,单机Region数大概500上下,Region数太多导致Flush都是小文件,写放大罪魁祸首。合并小于10g 的Region,将Region数降低到单机130+,写放大效应立刻降低了,可以减少机器数了。
一个批量写请求,RegionServer内写多个Region是串行的,这个角度减少Region数可以改善写延时。同时单个Region MemStore太大,ConcurrentSkipListMap的结构插入性能会降低。目前没发现减少Region后明显的写延时差别。杭州的同事分享过阿里对MemStore数据结构的优化,版本升级到1.4.8后可以评估能否用的到。
另外,大Region会导致Major Compact 压力更大。这个可以通过修改Compact Policy来解决。

HBase参数调整
增大内存

堆内存 50g->100g
堆外内存 100g->120g

大内存降低写放大效应,提高读缓存命中率,支持更高的吞吐能力。改善GC表现。

基础配置

hbase.regionserver.handler.count 192->384
hbase.ipc.server.callqueue.read.share 无->0.4
hbase.ipc.server.callqueue.handler.factor 无->0.2

两倍Region后,监控看当前Handler经常达到192上限,按其他公司经验调大一倍。有时能打到上限。
线程多可以减少队列等待时间,可能增加请求处理时间,监控看,调大能显著减少队列等待时间p99,请求时间p99没有明显变化。
读写分离主要是能降低p99,避免慢写入/高并发scan等耗时长的操作堵塞句柄。192个句柄时,等待队列的p99有时会持续在500ms-1s左右。调大到384,增加读写分离,等待队列p99就维持在100ms以下了。
5个句柄使用一个队列,是为了降低高并发时的锁资源争抢。需要权衡队列比例,如果1,2个句柄就使用一个队列,很容易几个慢请求就把队列里的后续请求都堵住了。目前设置为5:1.

MemStore

hbase.hstore.flusher.count 15-->8 flush线程数
hbase.regionserver.optionalcacheflushinterval 无->7200000 (1小时到2小时)
hbase.regionserver.hlog.blocksize 无 -> 268435456 (实际值没变,由使用hdfs块大小变为显式设置)
hbase.regionserver.maxlogs 52 -> 200

除了RegionServer重启时MemStore Flush外,有几种情况会触发MemStore Flush,分别是单个Region的MemStore达到上限,单个Region的MemStore距离上次Flush过了刷新周期,hlogs达到上限Flush涉及的还未Flush的Region,总MemStore达到内存设置上限。这几种情况按照从好到差顺序排列,越靠后对系统的稳定性影响越高,应尽量避免。
堆内存的增加,直接增大了MemStore内存上限,增大了单Region Flush的容量,可以刷大文件减少写放大效应。同时尽量让Region写满128MB再Flush,可以错开Flush时间,错开Compact时间,降低磁盘IO峰值,减少Flush和Compact排队现象。
10台均分Region,调整后单台的MemStore在10g到30g波动。为了尽量128MB在刷,其他几种Flush方式的参数要跟着调整。
虽然我们要避免后面几种Flush情况出现,但当业务突然有写入热点,或机器重启各Region的MemStore重置,可能会触发定时刷新/达到hlogs上限引起集中Flush。为降低同时Flush并发高引起的问题,降低了并发Flush数。由于MemStore足够大,单次Flush周期长,即使控制Flush并发,也不会充暴MemStore内存造成写堵塞。
此外,控制flush数可以间接控制Minor Compact的压力。
按10台RegionServer计算规模和请求量,白天绝大多数Region在2个内MemStore达到128MB,2小时刷新可以确保绝大多数region写满128MB自动刷新,减少写放大。如果按默认1小时,重启后的前2,3天里,会有很多Region在相同时间Flush,触发Compact,系统压力很大。2,3天后,靠着刷新时间每次的随机波动才能慢慢分散开。所以应确保白天峰值写入量时,大多数Region都能在刷新周期里写满Flush。
hlogs过少会造成刷新周期太短。以之前经常延时变长的一台服务器为例,平均5到10分钟强刷一次,刷的都是小文件,带来了严重的读写放大后果。之前Region数三倍于现在,和GC参数不合适一起造成了偶发的GC时间占比高影响业务的问题。 另外,目前hlogs 50的配置会造成同时Flush大量Region,同时Compact,系统压力大,造成请求和吞吐的毛刺。
maxlogs的配置多大合适?maxlogs 从90,到120,150,200,250,300,350,400都实验过,越大的hlogs对缓解Region写入不均,调大Flush尺寸和周期越有利 。
单纯按照流传的公式来看, 下限 50 * 1024/(256*0.95)= 210,上限60 * 1024/(256*0.95)= 252,应该在210到252之间。实际由于各Region会陆续触发flush,hlogs即使到达252,MemStore总内存可能只有10-20g,依然可以调大。
hlogs上限提高能解决重启后同时flush密集的问题。重启后,各region MemStore都是从0开始缓存,hlogs到上限时如果大量region没写满,会触发大量Region同时 Flush,这些Region的MemStore再次清零了,下个周期依然有大量Region同时Flush,打散速度慢于刷新周期触发的Flush。hlogs上限出发的同时Flush,Compact对GC压力很大,请求延时会周期性显著提升。如果256MB Flush,8台服务器,hlogs需要到400。128MB则200即可。
hlogs过多可能有什么影响?1.重启时间变长。重试时间长本质是总MemStore增大,Flush时间长造成的。之前17台规模单台重启大概1分钟,8台规模单台大概1分50秒,总时间并没有增加。再就是如果某台RegionServer挂掉,集群要重读未Flush的hlogs,hlogs多了会增加重读的量,增加集群负担。
综上所述,最终Flush Size定为128MB,hlogs上限定为200。

读Cache

hfile.block.cache.size 0.19 ->0.2
hbase.bucketcache.size 102400 -> 132000
hbase.bucketcache.percentage.in.combinedcache 0.9 -> 0.85

缓存大小配合堆内堆外内存增加的调整,缓存变成堆外上限112g,堆内20g。L1和L2的比例按实际线上情况由0.9调整为0.85.

Compact

hbase.regionserver.thread.compaction.small 6 -> 8
hbase.regionserver.thread.compaction.large 3 -> 4

略微提高Minor Compact和Major Compact速度,尤其是Major Compact速度,以便机器减少到一半时,夜里能Major完。调到12,GC压力过大,所以只是微调。

HDFS

dfs.client.hedged.read.threadpool.size 50 ->300 
dfs.client.hedged.read.threshold.millis 150->500
hbase.regionserver.hlog.slowsync.ms 无->400

Compact负载一高,200线程池会报大量的线程池满,资源不够用,所以调到300。
我们用多路读是为了当磁盘故障时,可以读其他副本。如果超时时间太低,可以读本地的去读了远程副本,显著增大集群网络和磁盘IO。读包括compact的读,是轻延时重吞吐的,集群磁盘IO负载高,延时增加,触发多路读又增大了集群的IO压力。尤其是本地化不是100%时,会读其他机器上的副本,400毫秒也依然容易超时,所以超时时间改为500,确保在一般的高负载和非本地化场景中,也不会给集群额外的压力,只有磁盘真正故障堵塞读的时候再读其他副本上。由于95%以上的读都来自内存缓存,500毫秒的最大超时时间并不会造成显著的读请求延时升高,毕竟常态的gc也要几百ms时间。
负载稍微高点,日志文件满屏都是WAL log slow,淹没了其他需要关注的问题。由于WAL是单线程顺序写单文件,写入速度是有瓶颈的,调到400,只有负载较高时才会打印。

GC参数调整
请看上一篇,本文不再叙述。

未来的工作
近期工作
打散Major Compact执行时间
现在集群内所有业务分组同一天晚上进行Major Compact,集群网络和磁盘IO压力大,存储量也会同时飙升。Major Compact即将打散到每周7天的晚上,以降低集群的压力。

换Compact Policy
Compact Policy优化,需要用户配合做客户端代码优化,和业务方暂定4月初共建。
现在所有业务用的都是默认的Default Policy,中规中矩。而该项目业务场景非常适合用Date Tiered Compaction,该策略能极大降低Compact写放大效应尤其是Major Compact的压力,并且提升近期热点数据查询速度。
更换该策略,需要业务方略微修改客户端代码,读写时增加TTL的设置,否则可能会降低查询速度。

换压缩算法
换高压缩比算法gz能进一步减少存储总量,已有经验是可以降低30%左右。即存储量视角,可以降到7台服务器规模。换压缩算法会增加CPU利用率,可能对用户读写造成未知的影响,待4月和用户共建。

中远期工作
2副本
好处是存储量立刻降低1/3,坏处是集群同时坏2块盘的概率比坏3块高得多,更容易丢数据。一般是偏离线,稳定性要求不高,存储量偏高的业务,数据在hive有一份,即使有数据缺失可以很快从Hive导一份。需要和用户进一步确定业务模式是否能采用。

超卖
目前成本分摊策略,独立业务分组按RegionServer服务器数分摊成本,如果独立业务分组存储总量大于分组机器所提供的存储总量,即认为存储量达到瓶颈。就必须要增加机器,不同的业务瓶颈不一样,按存储量严格限制,不利于提升集群资源的整体利用率。
所以从整个集群的资源利用率来看,允许部分吞吐,延时要求不高的业务使用更多的存储,即存储超卖,可以更有效提高集群资源利用率,释放数据引擎潜力,降低业务方使用成本,为公司省钱。
超卖涉及三个维度。超卖存储每TB价格,超卖存储量如何计算。超卖比例,
现在每TB成本是整机打包折算的,而超卖的存储只涉及纯磁盘的折算成本。要超卖存储,需要额外提供超卖存储的每TB价格,这个价格应该比整机的每TB成本低一些。
超卖存储量可以用定时程序收集分组的hdfs存储量,保留最高值,除0.9作为该月实际存储用量,减去分组机器数提供的存储就是超卖量。
超卖比例,前期可以先允许超卖分组存储的20%,并监控集群整体磁盘利用率情况。超卖试运行一段时间后,如果集群存储依然空闲,可以尝试提高超卖比例上限。
目前成本分摊的方式,只支持业务分组按整机打包折算,没有超卖的分摊方式。待评估实际需求后,再来决定是否允许超卖。
如果有业务方需要过高的超卖比例,不适用于现在的集群架构,需要考虑ssd和sata混部的架构。

SSD和Sata混部
目前业务按数据量和期望延时的不同分了两个集群,1个是SSD集群,一个是Sata盘集群。SSD读写更快,但成本高,存储量有限。
业内最顶尖的做法,是允许SSD和Sata盘混部,好处有2。一个是3副本一个是SSD2个是Sata盘,保证性能的同时降低存储成本。另一个是时间相关数据按时间分块存储在不同介质上,例如支付宝账单,3个月内SSD,1年内Sata盘,一年前的历史数据就存储在更便宜的存储介质上了。历史类数据都适合用这种方式。
混部的方式,在软件,集群架构,机器采购方面都有颇多挑战,是个长期的工作。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值