Spring Redis开启事务支持错误用法导致服务不可用

1.事故背景

在APP访问服务器接口时需要从redis中获取token进行校验,服务器上线后发现一开始可以正常访问,但只要短时间内请求量增长服务则无法响应

2.排查流程

(1)使用top指令查看CPU资源占用还远远达不到瓶颈,排查因为CPU资源不足导致服务不可用的可能

(2)查看tomcat线程池配置,默认最大线程数为200,理论上可以支持目前服务器的访问量

(3)使用jmap指令保存堆栈信息, jmap -dump:format=b,file=dump.log pid ,pid为进程

(4)使用Java visualVM打开保存的堆栈日志dump.log,发现绝大部分的线程都阻塞在从redis连接池中获取连接的代码,如下图所示

Spring Redis开启事务支持错误用法导致服务不可用

3.原理分析

根据堆栈日志所显示得知线程访问redis前需要从连接池队列中推出一个连接,当连接池没有连接时,则会阻塞等待,阻塞等待的时间可以自行设置MAA_WAIT参数,默认是-1表示不限时等待,目前项目使用默认配置,所以所有的线程都会一直阻塞在获取连接的步骤,如果设置了最大等待时间,当超过最大等待时间会报出Could not get a resource from the pool的异常

(1)在spring配置文件中的stringRedisTemplate对象配置参数中打开了事务支持,而redis的事务支持是用MUTI和EXEC指令来支持,以下事务实例截图来自菜鸟教程 https://www.runoob.com/redis/redis-transactions.html

Spring Redis开启事务支持错误用法导致服务不可用

Spring Redis开启事务支持错误用法导致服务不可用

(2)如果要保证在事务能正常执行,那么在一个方法中多次操作redis必须是同一条连接,这样才能保证事务能正常执行,所以在stringRedisTemplate会将连接绑定在当前线程,当第二次访问redis时直接从当前线程中获取连接,绑定连接源码如下:

Spring Redis开启事务支持错误用法导致服务不可用

(3)按照流程,先绑定连接,最后在finally代码块中释放连接,看起来并没有问题,但跳进去releaseConnection方法的代码发现连接需要在事务提交后才能释放,也就是说service方法上必须使用@Transation注解修饰,但因为业务方法上少写了@Transation注解导致连接将一直绑定第一次获取他的线程上,当线程池的线程被获取完之后,其他线程就会就如阻塞等待状态,导致服务不可用

Spring Redis开启事务支持错误用法导致服务不可用

(4)如果加上@Transation注解,那么方法执行完之后将会执行TransactionSynchronizationUtils.invokeAfterCompletion这个方法,mysql事务也是在这个方法执行commit操作,如下图所示方法的第一个参数是List<TransactionSynchronization> synchronizations,代表可以有多个事务,redis,mysql等,都会此进行事务提交操作,这里使用多态,根据对象的具体类型执行不同的方法,redis则执行redis的事务提交操作,mysql则执行mysql的事务提交操作

Spring Redis开启事务支持错误用法导致服务不可用

(5)以下为redis事务提交的代码,也跟我们上面提到的一样,发送exec指令提交事务

Spring Redis开启事务支持错误用法导致服务不可用

4.如何修改代码

(1)确认实际需求是否需要事务支持,如果需要则在对应方法上加上@Transaction注解

(2)如果不需要事务支持则将enableTransactionSupport设置为false

原文 

http://www.cnblogs.com/xiguadadage/p/13204080.html

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Spring Redis开启事务支持错误用法导致服务不可用

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址