问题描述
如下,生产hbase集群总是有一台服务器承担整个集群90%左右的读请求,
虽然qps100~200左右不能让regionserver宕机,但是近1年经常有收到反馈说hbase集群可能存在热点影响查询速度的问题,于是决定花时间排查
最终排查结果
phoenix的任意的一条查询类型的sql,在生成具体sql执行计划的时候,一般会多次查询表system.catlog表,system.catlog表目前部署在一台regionserver上,从而形成热点。
排查结果的补充说明
补充说明1:system.catlog是phoenix的元数据表,主要存储phoenix表与hbase表的字段对应关系和各种表状态
补充说明2:system.catlog数据量较少,为单个region,目前不支持分裂,只部署在一台regionserver上
补充说明3:phoenix查询时其,system.catlog所在regionserver将会接受到比其它集群更多的请求,所以从界面上看总有一台regionservr请求量高于其它regionserver。
补充说明4:以读取phoenix表数据为主的,并且有很多索引表的集群,system.catlog造成的热点情况会更加明显
建议处理方式
暂时无需处理。
原因1:查询system.catlog的逻辑初步判断为写死在phoenix源代码中,不能修改
原因2:system.catlog数据量较少并且查询效率很高,一般不是查询瓶颈
原因3:这种情况已存在至少1年,业务反馈正常
详细排查过程
鼠标点进regionserver的页面,如下图,我们可以看到所有region的读写请求计数
每次刷新这个页面,都能获取到当前所有region的请求数量情况
通过这个页面,可以手动收集数据(刷新-->页面全选-->复制到txt--->idea对比多个txt的不同),并且对比前后数据,计算出一段时间内region的请求数量的变化量
采样几十次之后,可以发现规律
会员日期索引表的部分region请求比较频繁,于是将这些频繁请求的region全部从现在的出现热点的regionserver4中转移了出去(move命令)。结果发现regionserver4的热点情况依旧,说明不是业务region热点region导致的
后续发现热点服务器regionserver
system.catlog的region的Filtered Read Request Count远远高于其它所有region
在测试环境研究一番后(具体验证办法见后续测试环境验证),决定尝试把system.catlog的region转移走。
于是把system.catlog的region从热点regionserver4中转移到了regionserver1(move命令),
转移前regionserver4是热点所在服务器
move命令之后,regionserver1瞬间变成了热点服务器,承担90%流量
至此,已足够说明system.catlog导致生产hbase出现热点服务器情况。
测试环境重现热点情况
首先,在测试环境建立一张有2kw数据的表,并且这张表的PK都是均匀分布的随机字符串,并且该表有二级索引表若干个
有如下压测程序,压测程序会生成随机字符串uuid,用uuid去查询PK获取一条数据,理论上请求是均匀没有热点的才对
然后使用jmeter对这个接口进行压测,可以发现system.catlog的region所在服务器请求量占到了整个集群的90%
将system.catlog的region转移到regionserver2
于是轮到regionserver2的请求量占用集群90%
源码部分排查
查询压测程序堆栈可以发现,目测有30%左右的请求线程在请求元数据表system.catlog,处于等待状态。从中可以发现具体的源码位置
发现:从systemcatlog中获取数据似乎被写死在代码中无法修改
发现:从源码来看,phoenix查询的主表关联的索引表越多,则查询system.catlog次数会增加
本地压力测试发现,如果优化得当,尽管phoenix会高频率的查询system.catlog表,简单的优化后的sql的qps仍然可以在1300+以上(如根据ID进行查询数据)。
单台服务器system.catlog表的查询效率至少可以到达3500+qps
可能的优化方案
给system.catlog表所在表做多副本,让其多个相同副本分布于其它服务器,分摊压力
方案缺点:需要另外花时间研究hbase多副本功能以及是否适用system.catlog表