controller调用另一个controller中的方法 获取返回值_程序员一个小配置导致Redis假死,大牛架构师5分钟找到问题根源...

新版本发布上线,正想偷懒休息一下子,就收到了来自测试反馈的BUG:某个功能不能用了,让我紧急排查一下。

我看了一下代码,逻辑不是很复杂,就是调用Service,Service里进行一些业务处理,最后更新并返回Redis缓存的值,Service代码大概是这样子的(省略不相干的内容):

1f6d7dcd8a874709bcc094b66bd432b5

缓存突然不返回结果了

一番排查下来,我发现是RedisTemplate的increment方法的返回值变成了null,就像假死了一样,所以导致业务出错。

  • 难道Redis坏了?

我打开可视化工具试着连上Redis,发现缓存数据存在,所以应该不是Redis的问题

  • 难道是代码的问题?

试一下吧,我们用两种方式分别来获取一下缓存对比一下,第一次从Service方法返回值,第二次我们直接从Redis取值,代码如下:

5d449d28c2794b13ba1650b93d3fe236

执行一下,我们来看一下对比结果:

702014d563a446eba32ade7f0b53cf19

可以看到,从Service方法里查询Redis返回值为null,从Controller直接查询Redis则是正常返回。

同一个结果,从不同的地方查询会返回不同的值,啥情况?

原来是事务惹的祸

看来这难题我是搞不定了,只好向我的架构师老大求救。

我给老大讲了一下奇怪的现象,一开始老大也觉得奇怪,后来想了想问我有没有改动Redis的配置文件,我这才想起来确实改了Redis的一个配置:

ff331f32f70b46bea6db1f2599f37a38

我开启了Redis的事务支持功能

事情是这样的:那天我正好闲着没事,就翻翻代码学习学习老大架构的精髓,不知怎的就看到了Redis的配置文件,RedisTemplate里面setEnableTransactionSupport属性,我心想Redis开启事务支持不挺好的嘛,鬼使神差地就给设置开启了,回头我也没当回事直接就发版了。

我把开启事务支持的配置去掉再一试,果然没问题了。

老大告诉我,Redis跟关系型数据库不太一样,开启事务支持以后,会自动执行multi命令接下来所有的命令都会进入一个队列Queue中等待,直到调用exec命令时才会真正顺序去执行,所以代码中拿不到返回值。

源码分析

因为RedisTemplate所有的方法最后都会执行execute方法,我们首先看一下execute方法:

620ede7e4d40445fb91e9f0ee0692870

我发现如果开启了事务支持,则会将连接与当前线程绑定,否则就直接获取一个新连接,我们主要看一下开启事务支持的情况,进到bindConnection方法,并最终跟到doGetConnection方法:

74ff5c3fe3724a5c90213b31973cc314

我发现如果开启了事务支持,会调用一个potentiallyRegisterTransactionSynchronisation的方法,名字还挺长的,进去看一下:

d246a78d5f3841c0b31095fa95d0ff2c

首先判断当前是不是处于一个事务当中,也就是判断我们有没有加注解,如果处在一个事务当中就会去自动调用multi命令,所以后面的命令都会首先进入队列等待,并立即返回null,直到执行exec命令才会真正执行命令,并一次性返回所有命令的执行结果。

另外老大跟我说:不建议启用redis事务,因为Redis对于事务的支持并不是很完善,事务中遇到错误不会回滚,Redis事务只能保证ACID中的隔离性和一致性,无法保证原子性和持久性。

还好老大给力,及时发现了问题所在才没有造成太大后果,否则我估计得被经理喷的体无完肤……

我是一名正儿八经的程序员,喜欢我的文章欢迎 转发 及 关注,我也会经常与大家分享工作当中的代码那些事儿。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值