phoenix更新压测时qps不到10并发低原因分析

本文详细记录了一次针对接口性能下降问题的排查过程,发现问题是由于Phoenix在处理带有二级索引表的更新操作时,行锁导致并发性能急剧下降。在压测中,相同入参导致行锁竞争激烈,接口QPS降低。通过堆栈分析和源码排查,确认行锁是问题根源。最终解决方案是在压测时使用不同的入参以减少锁竞争,从而提升QPS。
摘要由CSDN通过智能技术生成

背景

接口业务逻辑复杂又长,涉及到redis、fegin、phoenix。

测试同事对该接口进行压测,发现该接口qps在压测5分钟后qps会降低至10左右,

开发同事怀疑phoenix导致

主题

phoenix更新压测时并发低的原因

最终结论

phoenix行锁导致

对于一张有二级索引表的phoenix主表,在更新主表某条数据时, 如果需要更新索引表,则phoenix会对该行数据添加行锁,从加锁到解锁过程一般持续200毫秒到500毫秒,该过程中其它线程无法更新这条数据。

最终处理方式

压测时采用不同的入参,避免行锁竞争,压测qps就能上去

排查过程

======================2021年11月临时处理============================

刚刚遇到这个问题时,以为只是单次接口调用稍稍慢点(1s),只要压测的时候压测线程多些,qps就能上来,当后面发现并不能

压测程序用1个线程--qps为10

压测程序用2个线程--qps为13.5

压测程序用5个线程--qps为12.4

压测程序用30个线程--qps 13.2

压测程序用200个线程--qps 12.4

后面继续排查,发现接口在调用phoenix更新方法速度特别慢,phoenix更新就是性能瓶颈,但是这个更新是根据id进行更新的,并且只更新少量字符串数据,按理来说应该很快才对

此时由于时间紧张,代码要上线了,于是临时把phoenix的代码改成了连接hbase的代码,qps恢复到300+,后续再排查问题

======================遇事不决,实验排除法============================

遇事不决,改服务器配置提高性能!!

在hbase集群添加如下配置,增加服务端线程数

<property>

<name>phoenix.query.threadPoolSize</name>

<value>100</value>

</property>

<property>

<name>phoenix.query.targetConcurrency</name>

<value>100</value>

</property>

<property>

<name>phoenix.query.maxConcurrency</name>

<value>120</value>

</property>

结果没有用,经过几轮压测后发现,根据id进行修改的接口qps还是11.2,说明调节phoenix的线程数量还是不行

遇事不决,实验排除法!!

找另外一次测试环境151,采用相同的主表结构,主表数据差不多进行查询和更新压测

发现:另一个测试环境qps200左右还算可以,qps差是31这个测试环境的问题

在测试环境新建31一张主表结构一样的表,将这个新表的数据增加到80w,然后继续进行更新压测,多次压测后qps仍然是200左右

证明:qps差可能和phoenix配置无关,和表有关,

猜测:我新建立的主表没有索引表,所以可能是索引表会降低qps

行动:在151环境建立索引表,此时151该表数据2kw,建立一个二级索引表

create index IDX_COUPON_TEST7_MEMBER_ID on COUPON_TEST7(MEMBER_ID);

上面的sql运行花了300秒,

索引表建立好了,然后进行压测

结果:第一次压测qps只有29

第二次压测qps qps只有12.3左右

证明:qps低和索引表有关

行动:试图删除索引表后重试压测,2kw数据的索引表,4秒删完了,hbase中索引表也消失了

结果:压测qps恢复为200了

再次证明:qps低确实和索引表有关

=====================线程堆栈分析、源码排查===============

虽然通过实验,证明qps差的原因和索引表有关,但是根本改进措施还不清楚,更深的原因还需要继续排查

151hbase测试环境新建表COUPON_TEST6,

以及各种索引表

IDX_COUPON_TEST9_ALL

IDX_COUPON_TEST9_MEMBER_ID

IDX_COUPON_TEST9_MEMBER_NO

........

然后使用如下sql进行压力测试

upsert into COUPON_TEST9 (PK,STATUS,MODIFICATION_DATE,MEMBER_ID) values ('021000872418880','2','2021-10-30 11:06:23','123456')

压测时入参都是固定的不变的参数,即不过压多少次都是同一条sql在更新

压测2小时后,qps降低到每分钟15个请求(50线程下)

通过idea的线程堆栈导出,发现了大量springmvc的线程阻塞情况如下

可发现这些线程在请求hbase的时候被阻塞了,因此阻塞方是hbase集群

查看hbase服务器日志,发现索引表的类在报错超时

后续使用debug dump将服务端的一个regionserver3服务器(主表更新region所在服务器)的线程堆栈拉取下来

可以发现有很多负责处理hbase请求的线程卡在一些地方长达5秒。通过堆栈可以发现,在hbase修改表的时候,会触发phoenix的协处理器,然后去更新索引表,在索引表的更新方法里有一个锁

根据堆栈,通过观察源码可以发现行锁代码如下

其中Lock类的tryLock方法会尝试获取锁,如果一直获取不到锁,就会阻塞到指定的时间

waitDuration是int,为30000 (毫秒),通过上图源码发现,这个锁和rowkey有关,可能是一个rowkey一个锁,应该是行锁

至此,已确认phoenix在并发更新同一条数据时qps很低的原因,为行锁导致

测试同事压测时,使用了相同的入参,因此更新的sql也相同,对于有索引表的情况,行锁竞争很激烈,所以接口很慢

最终处理方式:压力测试的时候使用不同的入参,入参不同则可降低锁竞争,qps则会提高

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值