前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mq要如何处理消息丢失、重复消费?

mq要如何处理消息丢失、重复消费?

作者头像
苏三说技术
发布2020-10-15 14:41:55
1.3K0
发布2020-10-15 14:41:55
举报
文章被收录于专栏:苏三说技术苏三说技术

如果要你实现一个支付宝向余额宝转账的功能,比如:账户a从支付宝转出5000余额宝转入5000,该怎么做呢?

可能有些人会说,这还不简单,直接上图

支付宝先给账户a减5000,调用余额宝的接口给余额宝的账号b加5000。

用这种方式正常情况下是可以的,如果出现以下问题该怎么办呢?

  1. 调用余额宝api时网络失败了
  2. 调用余额宝api时网络超时了
  3. 如果余额宝api业务逻辑比较复杂,耗时比较长,用户需要长时间的等待才有结果,用户体验不好

有人说:如果调用余额宝api时网络失败了,对接口进行重试不就可以解决问题了。

:你是用同步重试,还是异步重试呢?

如果用同步重试,即在调用余额宝api时获取返回值,如果发现失败立刻重试3次。调用一次余额宝api的耗时为n秒,重试3次的耗时则为3n秒,接口响应时间增加了两倍,增加了接口超时的风险。如果重试3次之后,还是失败该怎么处理?

如果用异步重试,第一次调用余额宝api时,不管是成功还是失败,都直接给用户返回成功。如果是失败,后台开启一个线程,不断重试一直到成功为止。如果在不断重试的过程中服务器重启了,该怎么办?

又有人说:如果调用余额宝api时网络超时了,不知道上次请求是成功还是失败,再重试一下不行吗?

:不是不,第一.余额宝必须做幂等性设计,不然余额宝这边多转入5000怎么办?余额宝肯定不会犯这种错误。第二.同样会面临如果调用余额宝api时网络失败了的问题。

再有人说:如果余额宝api业务逻辑比较复杂,耗时比较长,用户需要长时间的等待才有结果,用户体验不好。改成异步就可以解决这个问题了。

答:改成异步可以提前告知用户结果,然后在后台通过补偿机制不断的重试,让数据达成最终一致性,这种方式对用户体验可能确实要好一些。异步处理又分为:开启线程 和 使用mq。线程处理有比较致命的弊端,如果服务器重启,线程里的数据会丢失。

接下来,我们的重点放在mq上。

余额宝给账户a减了5000之后,给指定topic1发一条消息,然后余额宝从topic1消费这条消息,给账户b加5000。

对于问题1,如果余额宝处理失败了,比如像rocketmq这类消息处理框架会把消息放入重试队列重试16次,不需要业务代码做额外的工作。

对于问题2,如果服务器重启了,由于消息保存在服务端的磁盘上,不会丢失,客户端可以通过offset从服务端重新获取消息,它能够保证消息至少被余额宝消费一次。

对于问题3,支付宝给账户a减了5000发送完消息之后,可以直接返回成功,然后余额宝作为消费者在后台默默执行,一直到成功为止。

那么问题又来了:

如果余额宝消费了消息,业务处理失败了怎么办?这个就是所谓的消息丢失。

要解决消息丢失就需要建一张消息发送表,如图:

支付宝从账户a减5000,接着往本地消息表中写入一条消息记录,confirm_status为待确认,然后发送mq消息。注意,支付宝这边的扣款和写本地消息表要在同一事务中。

余额宝消费消息给账户b加5000之后,调用支付宝消息确认api,修改confirm_status为已确认。

如果余额宝这边消息丢失了,支付宝有个job会每个5分钟扫描一次本地消息表中confirm_status为待确认状态的记录,重新发送一次消息,这样余额宝又可以重新处理了。

那么还有个问题:

余额宝这边处理成功,但是由于调用 支付宝消息确认api失败,导致支付宝的job重新发送消息,余额宝重复消费了。这个就是所谓的重复消息。

重复消费要如何解决呢?

余额宝也增加一个本地消息表,记录业务处理成功的消息。当然余额宝的账号操作和本地消息表也要在同一个事务中。

余额宝消费消息之后,先从余额宝的本地消息表中查一下,该消息有没有消费过,如果已经消费过了,则直接调用支付宝消息确认api,修改confirm_status为已确认,避免下次支付宝的job重复发消息。如果从余额宝的本地消息表中查到没有消费,则给账户b增加5000,同时往本地消息表写一条记录,然后调用支付宝消息确认api。

总结:通过在mq的生产者和消费者两端分别增加本地消息表,并且在生成者端增加定时job扫描待确认状态的记录,重新发送消息,可以解决:消息丢失重复消费 问题。当然实际的支付宝向余额宝转账的场景更复杂,在高并发的情况下,可能需要用分布式锁,防止金额异常。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 苏三说技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档