一、事故场景
线上用户突然反馈说商品修改了名称之后无法搜索出来。项目为电商项目,商家端在编辑了商品名称之后,C端用户无法在商品搜索栏中使用修改之后的名称搜索该商品,说白了就是修改并没有生效。
二、原因排查
商品搜索使用的是 ES 搜索引擎,想要搜索商品的话需要生成该商品索引,而生成商品索引的逻辑是,商品添加或编辑之后会触发并发送 MQ 消息到 ES 搜索微服务中,搜索微服务收到消息后根据提供的商品ID到商品表中获取商品信息并生成商品索引数据。
根据用户提供的商品ID和大概修改时间,从商品索引生成日志中找到了该商品索引的生成日志,也就是说商品是成功被索引了,但从打印的商品信息发现获取的商品数据是修改之前的商品数据。
真相: 至此,已经可以知道原因了,在商品编辑逻辑中,确实是对商品 insert
或 update
之后再发送 MQ 消息的,但消息接收之后去获取到的商品数据是旧的未提交成功的数据。也就是说这里存在一个时间差,从发送 MQ 到被消费这一过程,数据库的增加或者更新操作事务没有提交成功。
三、解决问题
这种问题发生的可能性比较小,但确实会存在这种问题,所以为了避免这种情况的发生,可以注册一个事务异步管理器:
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
// 发送 MQ
}
}
);
这样的话就可以保证事务提交之后再生成的商品数据一定是最新的。但需要注意的一点的是,如果使用事务异步管理器的话,一旦异步事务管理器中的操作出错了,整个事务是不会回滚的,这个是需要留意的。