【线上问题】RC事务+缓存 引发的连续更换物品信息变空

122 阅读2分钟

一、问题描述

线上最近爆出一些连续更换两次物品信息,物品信息会被置为空的情况,感觉很懵,开始分析历史逻辑,分析完觉得蛮有意思,想跟大家分享一下。

1.问题背景:我们的业务场景可以支持用户更换某智能配件,但由于配件较为核心,为了不影响用户的体验,需要将原配件的信息赋值到新换到的配件上。
:物品更换前,新物品内数据为空,是一个几乎空白信息的物品。

2.问题定位:经过分析,问题定位在 RC隔离级别事务 和 缓存 的共同作用下导致的。

3.主流程:我们现在假设将配件A更换为配件B,简单来说就是将A置为空,并报废,同时将A的数据赋予B。

二、原因分析

问题的奇怪之处在于为什么第一次更换物品不会有这种问题,只有第二次才会触发这样的问题呢? 排查发现,由于查询配件详情方法会带有缓存5min的逻辑,而更换配件的流程中间会有调用户服务配件绑定关系的rpc接口,此rpc接口中会涉及到新、旧配件查询的方法,此时主流程的事务并未提交,并且隔离级别是RC(读已提交),也就是说将A的信息置空和赋值B都还没有被持久化,这就会导致B的缓存被置为空。看下图,第一次更换配件,其实如果就此结束,除B配件的缓存被赋值为空以外,还不会有什么问题。

原逻辑.png

但如果此刻商家在第一次配件A更换为配件B后,效果不满意,5min内立马又将配件B更换为配件C,这个问题就会被触发。
因为在5min内,配件B的缓存为空,此时去更换为C的时候,就会将配件B的缓存空赋值到C上,最后给到用户的将是一个空白的配件C,这样当然会引起客诉。确定根因后,立马开始改造系统,如下图:

优化后逻辑.png

三、解决方案

优化策略其实并不复杂,我采取的方案就是:
1.将之前的rpc改为异步的消息,保证主流程对物品物权变换的rpc并不持续关注;
2.同时立即commit,将事务提交,将主流程数据及时落库;
3.对于一些可以后置的操作,剥离出整体的事务,在提交事务后进行处理。
这样在更换用户对于配件的绑定关系时,查询到的就已经是持久化后的数据了,则不会对后续产生任何影响,也就可以避免此次线上遇到的这种问题。