关于后端:一次-Redis-事务使用不当引发的生产事故

41次阅读

共计 1318 个字符,预计需要花费 4 分钟才能阅读完成。

一、前言
最近我的项目的生产环境遇到一个奇怪的问题:
景象:每天早上客服人员在后盾创立客服事件时,都会创立失败。当咱们重启这个微服务后,后盾就能够失常创立了客服事件了。到第二天早上又会创立失败,又得重启这个微服务才行。
初步排查:创立一个客服事件时,会用到 Redis 的递增操作来生成一个惟一的分布式 ID 作为事件 id。代码如下所示:
return redisTemplate.opsForValue().increment(“count”, 1);
复制代码
而凑巧每天早上这个递增操作都会返回 null,进而导致前面的一系列逻辑出错,保留客服事件失败。当重启微服务后,这个递增操作又失常了。

那么排查的方向就是 Redis 的操作为什么会返回 null 了,以及为什么重启就又恢复正常了。

二、排查
依据下面的信息,咱们先来看看 Redis 的自增操作在什么状况下会返回 null。
2.1 揣测一
依据重启后就恢复正常,咱们揣测早晨执行了大量的 job,大量 Redis 连贯未开释,当早上再来执行 Redis 操作时,执行失败。重启后,连贯主动开释了。
然而其余有应用到 Redis 的业务性能又是失常的,所以揣测一的方向有问题,排除。
2.2 揣测二
可能是 Redis 事务造成的问题。这个揣测的根据是依据上面的代码来排查的。
间接看 redisTemplate 递增的办法 increment,如下所示:

官网正文曾经阐明什么状况下会返回 null:

当在 pipeline(管道)中应用这个 increment 办法时会返回 null。
当在 transaction(事务)中应用这个 increment 办法时会返回 null。

事务提供了一种将多个命令打包,而后一次性、有序地执行机制.
多个命令会被入列到事务队列中,而后按先进先出(FIFO)的程序执行。
事务在执行过程中不会被中断,当事务队列中的所有命令都被执行结束之后,事务才会完结。(内容来自 Redis 设计与实现)

持续看代码,发现在操作 Redis 的 ServiceImpl 实现类的下面增加了一个 @Transactional 注解,揣测是不是这个注解影响了 Redis 的操作后果。
2.3 验证揣测二
如上面的表格所示,第二行中没有增加 Spring 的事务注解 @Transactional 时,执行 Redis 的递增命令必定是失常的,而接下来要验证的是表格中的第一行:加了 @Transactional 是否对 Redis 的命令有影响。

为了验证下面的推论,我写了一个 Demo 程序。
Controller 类,定义了一个 API,用来模仿前端发动的申请:

Service 实现类,定义了一个办法,用来递增 Redis 中的 count 键,每次递增 1,而后返回命令执行后的后果。而且这个 Service 办法加了 @Transactional 注解。

Postman 测试下,发现每发一次申请,count 都会递增 1,并没有返回 null。

而后到 Redis 中查看数据,count 的值也是递增后的值 38,也不是 null。

通过这个试验阐明在 @Transactional 注解的办法外面执行 Redis 的操作并不会返回 null,论断我记录到了表格中。

所以说下面的推论不成立(加了 @Transactional 注解并不影响),到这里线索仿佛断了。

正文完
 0