跳到主要内容
弗美科技
技术分享

RabbitMQ 把订单和短信拆开

下单接口原来同步干四件事:写库、发短信、推企业微信、记日志,慢的时候 1.2 秒。把后三件丢进 RabbitMQ,接口只留写库和投递消息,降到 200 毫秒出头。踩过两个坑:消息没开持久化重启丢了 6 条、消费者没做幂等重复发了一次短信。

2023年3月24日消息队列解耦下单

一个下单接口,测下来平均 1.2 秒,慢的时候到 2 秒多。拆开看,真正写订单表只花 100 多毫秒,剩下时间全在等三件不急着要结果的事:发确认短信、往企业微信群推一条、写一份详细日志。

拆法

接口里只留两件:写订单、往 RabbitMQ 投一条消息。消息体很小,就 order_id 加一个事件类型。剩下三个动作各一个消费者,自己取、自己重试。

改完接口平均 200 毫秒出头。用户点完立刻看到成功页,短信晚个一两秒没人察觉。

1. 没开持久化,重启丢了 6 条

第一版图省事,队列和消息都用的默认配置。有天晚上服务重启,队列里 6 条待发消息没了,6 个用户没收到确认短信。查日志才发现的,用户其实没投诉。

改法:队列 durable、消息 delivery_mode 设 2、生产者开 confirm。三样一起才算稳。交换机那边也标了持久化。

2. 消费者没做幂等,短信发了两遍

有个消费者处理完业务逻辑才 ack,中间网络抖了一下没 ack 上,消息重新投递,短信发了第二次。用户收到两条一模一样的。

后来把 ack 提前到业务之前?不行,会丢。改成业务里按 order_id 加 event_type 做去重表,插入成功才真发,重复的直接 ack 掉。跟积分那套幂等键是一个思路。

3. 死信队列

一直失败的消息不能无限重试,会把队列堵住。设了最多 3 次,超过进死信队列,同时在监控里计数,超过 5 条就告警。运维值班的表上多了一行「看死信长度」。

4. 顺序不保证

企业微信那条提醒偶尔比订单成功的日志还早到,看着别扭但不影响什么。我们没强求顺序,在消息体里带了 occurred_at,展示时按这个时间排。为了顺序上单分区队列,这笔账不划算。

后来

三个消费者现在还能单独停。有回短信服务商故障,我们把那个消费者停了两小时,下单照常,恢复后一起补发。搁以前,短信一挂,整个下单跟着卡。

那 6 条丢掉的消息后来是照着订单表补发的,补完在文档里记了一笔:默认配置不能信。

商务咨询 · 免费初步沟通

需要针对你的场景给个建议?

把业务背景和当前系统情况告诉我们,我们会给出可执行的思路。

在线留言

周一至周五 9:00–18:00 · 工作日 9:00–18:00 响应,留言会在一个工作日内回复。

商务微信
商务微信二维码

扫一扫,加商务微信咨询服务与方案报价

或填写需求表单