2021-01-07

博客园Logo
首页
新闻
博问
专区
闪存
班级
代码改变世界
搜索
注册
登录
返回主页
程序通事
个人博客网站:https://studyidea.cn/
博客园
首页
新随笔
联系
订阅
管理
抄答案就是了,两套详细的设计方案,解决头疼的支付掉单问题
Hello,大家好,我是楼下小黑哥~

好久没写支付相关的文章了,今天继续从事老本行~

上次在文章钱被扣走了,但是订单却未成功!支付掉单异常最全解决方案提到,支付过程会出现掉单、卡单的情况,这种情况对于用户来讲,体验非常差,明明自己付了钱,扣了款,但是订单却未成功。

上篇文章我们简单说了下解决方案,这次小黑哥就结合生产实际碰到的情况,给出两种详细设计的方案:

定时轮询补偿方案
延迟消息补偿方案
大家可以根据自己系统的实际情况,选择性参考。

当然了,以下设计方案可能并不完美,如果各位读者还有其他解决方案,欢迎留言指出,一起讨论,一起成长~

欢迎关注我的公众号:小黑十一点半,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

定时轮询补偿方案
整体流程
这个方案主要采用定时任务,批量查询掉单记录,从而驱动查询具体支付支付结果,然后更新内部订单。

整体方案流程图如下:

定时任务补偿

前三步流程没什么好说的,正常的支付流程,咱们针对后面几步具体详细说下。

第三步调用支付通道之后,如果支付通道端返回支付受理成功或者支付处理中,我们就需要调用第四步,将这类订单插入掉单表。

如果支付直接成功了,那就正常流程返回即可。

复习一下,网关类支付,比如支付宝、微信支付、网银支付,这种支付模式,支付通道仅仅返回支付受理成功,具体支付结果需要接收支付通道端的支付通知,这类支付我们将其称为异步支付。

相应的还有同步支付,比如银行卡支付,微信、支付宝代扣类支付,这类支付,同步就能返回支付结果。

第五步,补单应用将会定时查询数据库,批量查询掉单记录。

第六步,补单应用使用线程池,多线程异步的方式发起掉单查询。

第七步,调用支付通道支付查询接口。

重点来了,如果第七步支付结果查询为以下状态:

支付结果为扣款成功
支付结果为明确失败
掉单记录查询达到最大次数
第八步就会删除掉单记录。

最后,如果掉单查询依旧还是处理中,那么经过一定的延时之后,重复第五步,再次重新掉单补偿,直到成功或者查询到达最大次数。

相关问题
为什么需要新建一张掉单表?不能直接使用支付订单表,查询未成功的订单吗?

这个问题,实际上确实可以直接使用的支付订单表,然后批量查询当天未成功的订单,补单程序发起支付查询。

那为什么需要新建一张掉单表?

主要是因为数据库查询效率问题,因为支付订单表每天都会大量记录新增,随着时间,这张表记录将会越来越多,越来越大。

支付记录越多,批量范围查询效率就会变低,查询速度将会变慢。

所以为了查询效率,新建一张掉单表。

这张表里仅记录支付未成功的订单,所以数据量就会很小,那么查询效率就会很高。

另外,掉单表里的记录,不会被永久保存,只是临时性。当支付结果查询成功,或者支付结果明确失败,再或者查询次数到达规定最大次数,就会删除掉单记录。

这就是第八步为什么需要删除掉单表的原因。

如果需要保存每次掉单表查询详情,那么这里建议再新增一张掉单查询记录表,保存每一次的查询记录。

针对这个方案,如果还有其他问题,欢迎留言。

方案优缺点
定时轮询补偿方案,最大的优点可能就是系统架构方案比较简单,比较容易实施。

那么这个方案的缺点主要在于定时任务上。

定时任务轮询方案天然会存在以下不足:

轮询效率稍低

每次查询数据库,已经被执行过记录,仍然会被扫描(补单程序将会根据一定策略决定是否发起支付通道查询),有重复计算的嫌疑

时效性不够好,如果每小时轮询一次,最差的情况下,时间误差会达到1小时

如果为了解决时效性问题,增加定时任务查询效率,那么 1 中查询效率跟 2 的重复计算问题将会更加明显。

延迟消息补偿方案
下面介绍另外一种掉单补偿方案,延迟消息补偿方案,这个方案整体流程与定时任务方案类似,最大区别可能在于,从一种拉模式变成一种推模式。

整体方案流程图如下:

这个方案主要流程跟定时方案类似,主要区别在于第四步,第五步,第八步。

第四步的流程从插入掉单表变更为往延迟队列发送掉单消息。

第五步,补单程序接收掉单消息,然后触发支付掉单查询。

第八步,如果第七步支付结果查询为以下状态:

支付结果为扣款成功
支付结果为明确失败
掉单记录查询达到最大次数
补单程序将会告知延迟队列消费成功,延迟队列将会删除这条掉单消息。

其他状态将会告知消费失效,延迟队列将会在一定延时之后,再次发送掉单消息,然后继续重复第五步。

延迟队列
这里的延迟队列需要自己实现,复杂度还是比较高的,这里给大家推荐几种实现方案:

第一种,基于 Redis SortedSet 实现延迟队列。可以参考一下有赞的实现方案https://tech.youzan.com/queuing_delay/

第二种,基于时间轮算法(TimingWheel)实现延迟队列,具体可以参考 Kafka 延时队列。

第三种,基于 RocketMQ 延迟消息。

前两种方案说起来还需要再开发,所以还是比较复杂的。

这里重点说下第三种方案,该方案是 RocketMQ 已经支持的特性,开箱即用,使用起来还是比较简单的。

RocketMQ 延迟消息支持 18 个等级,分别如下:

1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
消息发送方可以通过以下方式指定延迟等级,对应上方的延迟时间。

Message#setDelayTimeLevel
消息消费方,如果消费失败,默认将会在消息发送方的的延迟等级基础上加 1。如果消息消费方需要指定其他的延迟等级,可以使用如下方式:

ConsumeConcurrentlyContext#setDelayLevelWhenNextConsume
RocketMQ 延迟消息,支持的特性还是比较基础、简单,不支持自定义延迟时间。不过对于掉单补偿的这个场景刚好够用,但是如果需要自定义延迟的,那还是得采用其他的方案。

方案优缺点
延迟消息的方案相对于定时轮询方案来讲:

无需再查询全部订单,效率高
时效性较好
不过延迟消息这种方案,需要基于延迟队列,实现起来比较复杂,目前开源实现也比较少。

小结
支付掉单、卡单是支付过程中经常会碰到的事,我们可以采用异步补偿的方案,解决该问题。

异步补偿方案可以采用如下两种:

定时轮询补偿方案
延迟消息补偿方案
定时轮询补偿方案实现起来比较简单,但是时效性稍差。

而延迟消息补偿方案总体来说比较优秀,但是实现起来比较复杂。如果没有自定义的延迟时间的需求,可以直接采用 RocketMQ 延迟消息,简单快捷。

另外延迟队列使用场景还是比较多,不仅仅能用在掉单补偿上,还可以用于支付关单等场景。所以有能力开发的团队,可以开发一个通用的延迟队列、

好了,今天的文章就到这里了。

我是楼下小黑哥,下篇文章再见,886~

欢迎关注我的公众号:小黑十一点半,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

历史支付文章推荐
钱被扣走了,但是订单却未成功!支付掉单异常最全解决方案
一笔订单,但是误付了两笔钱!这种重复付款异常到底该如何解决?
收款神器!解读聚合收款码背后的原理|原创
手机没网了,却还能支付,这是什么原理?|原创
轻轻一扫,立刻扣款,付款码背后的原理你不想知道吗?|原创
支付渠道路由系统进化史
从零开始设计对账系统
微信支付宝接入大全
多支付通道路由网关设计
银行卡支付,背后到底发生了什么?
欢迎关注我的公众号:小黑十一点半,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

标签: 支付系统
好文要顶 关注我 收藏该文
楼下小黑哥
关注 - 11
粉丝 - 99
+加关注
1
« 上一篇: 30G 上亿数据的超大文件,如何快速导入生产环境?
posted @ 2021-01-07 08:36 楼下小黑哥 阅读(249) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】有你助力,更好为你——博客园用户消费观调查,附带小惊喜!
【推荐】AWS携手博客园为开发者送福利,注册立享12个月免费套餐
【推荐】七牛云新老用户同享 1 分钱抢 CDN 1TB流量大礼包!
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻

相关博文:
· 膜拟抄
· 膜拟抄
· 膜拟抄
· 摘抄sql优化
· 简单模板摘抄
» 更多推荐…

最新 IT 新闻:
· 互联网新巨头二号位简史
· BAT移动生态战争2021:对生态的研究和发力成为重中之重
· 《绝地求生》续作或正在开发 登陆PC/主机/移动端
· 特斯拉与BBA,必有一战
· 一线|瑞幸郭谨一回应被“逼宫”:举报信是陆正耀等起草,当事员工不知情
» 更多新闻…
历史上的今天:
2020-01-07 2020 年的第一天,程序员鸭血粉丝又碰上生产事故
公告
关注公众号
→「技术干货推送」
→ 加w-x:xu952685333

我的博客
studyidea.cn
昵称: 楼下小黑哥
园龄: 2年6个月
粉丝: 99
关注: 11
+加关注
< 2021年1月 >
日 一 二 三 四 五 六
27 28 29 30 31 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 1 2 3 4 5 6
搜索

我的标签
Java(68)
支付系统(11)
dubbo(10)
Spring(8)
IDEA(7)
Redis(5)
踩坑经历(4)
开发工具(4)
系统设计(3)
MySQL(2)
更多
积分与排名
积分 - 160494
排名 - 4676
随笔分类
IDEA(4)
Spring(6)
第三方支付(1)
随笔档案
2021年1月(1)
2020年12月(4)
2020年11月(2)
2020年10月(2)
2020年9月(5)
2020年8月(3)
2020年7月(4)
2020年6月(6)
2020年5月(4)
2020年4月(7)
2020年3月(10)
2020年2月(6)
2020年1月(4)
2019年12月(2)
2019年11月(5)
更多
最新评论

  1. Re:数据库读写分离这个坑,你应该踩过吧?
    mark

–wwr01
2. Re:30G 上亿数据的超大文件,如何快速导入生产环境?
我有点疑惑, 30GB这种超大文件,写入和读取都用的什么方法啊。文件这么大,是不是只能追加数据,都无法修改数据?

–荆棘人
3. Re:30G 上亿数据的超大文件,如何快速导入生产环境?
@Jacklondon Chen @楼下小黑哥 @Jacklondon Chen 怎么说呢,我当时直接使用 mybatis 组装批量 insert 语句的方式,不是使用你这种方式。 另外的,我的业务场…
–非我在
4. Re:30G 上亿数据的超大文件,如何快速导入生产环境?
@blogger2020 文件其实就是下面这种格式: AA||BB||CC||DD 程序就是解析出来,然后转化成插入到自己业务表中…
–楼下小黑哥
5. Re:30G 上亿数据的超大文件,如何快速导入生产环境?
楼主: 要是有可能,您是否可以分享一个 sample file, 1 ~ 2M 的压缩文件就行。看看我们能否也做点测试,幸运的话,我们也能发表一些与测试有关的文章,体会? Sample file 发布…
–blogger2020
阅读排行榜

  1. 聊聊银企直联服务那些事(9679)
  2. IDEA Debug 无法进入断点的解决方法(8993)
  3. 求求你了,不要再自己实现这些逻辑了,开源工具类不香吗?(6984)
  4. 手机没网了,却还能支付,这是什么原理?(6386)
  5. Spring 注解编程之 AnnotationMetadata(5411)
    评论排行榜
  6. 求求你了,不要再自己实现这些逻辑了,开源工具类不香吗?(44)
  7. 30G 上亿数据的超大文件,如何快速导入生产环境?(32)
  8. 我还在生产玩 JDK7,JDK 15 却要来了!|新特性尝鲜(26)
  9. 手机没网了,却还能支付,这是什么原理?(23)
  10. 钱被扣走了,但是订单却未成功!支付掉单异常最全解决方案(21)
    推荐排行榜
  11. 坚持写作快两年了,有些私藏工具跟你们分享(44)
  12. 手机没网了,却还能支付,这是什么原理?(32)
  13. 数据库读写分离这个坑,你应该踩过吧?(28)
  14. 收款神器!解读聚合收款码背后的原理(28)
  15. 钱被扣走了,但是订单却未成功!支付掉单异常最全解决方案(22)
    Copyright © 2021 楼下小黑哥
    Powered by .NET 5.0 on Kubernetes
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值