🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
前言
最近测试给我提了一个bug,说我之前提供的一个批量复制商品的接口,产生了重复的商品数据。
追查原因之后发现,这个事情没想象中简单,可以说一波多折。
1. 需求
产品有个需求:用户选择一些品牌,点击确定按钮之后,系统需要基于一份默认
品牌的商品数据,复制出一批新
的商品。
拿到这个需求时觉得太简单了,三下五除二就搞定。
我提供了一个复制商品的基础接口,给商城系统调用。
当时的流程图如下:
如果每次复制的商品数量不多,使用同步接口调用的方案问题也不大。
2. 性能优化
但由于每次需要复制的商品数量比较多,可能有几千。
如果每次都是用同步接口的方式复制商品,可能会有性能问题。
因此,后来我把复制商品的逻辑改成使用mq
异步处理。
改造之后的流程图:
复制商品的结果还需要通知商城系统:
这个方案看起来,挺不错的。
但后来出现问题了。
3. 出问题了
测试给我们提了一个bug,说我之前提供的一个批量复制商品的接口,产生了重复的商品数据。
经过追查之后发现,商城系统为了性能考虑,也改成异步了。
他们没有在接口中直接调用基础系统的复制商品接口,而是在job
中调用的。
站在他们的视角流程图是这样的:
用户调用商城的接口,他们会往请求记录表
中写入一条数据,然后在另外一个job
中,异步调用基础系统的接口去复制商品。
但实际情况是这样的:商城系统内部出现了bug,在请求记录表中,同一条请求产生了重复的数据。这样导致的结果是,在job中调用基础系统复制商品接口时,发送了重复的请求。
刚好基础系统现在是使用RocketMQ
异步处理的。由于商城的job一次会取一批数据(比如:20条记录),在极短的时间内(其实就是在一个for循环中)多次调用接口,可能存在相同的请求参数连续调用复制商品接口情况。于是,出现了并发插入重复数据的问题。
为什么会出现这个问题呢?
4. 多线程消费
RocketMQ
的消费者,为了性能考虑,默认是用多线程并发消费的,最大支持64
个线程。
例如:
@RocketMQMessageListener(topic = "${com.susan.topic:PRODUCT\_TOPIC}",
consumerGroup = "${com.susan.group:PRODUCT\_TOPIC\_GROUP}")
@Service
public class MessageReceiver impl