电商之收单系统的webhook推送重试机制

文章目录

  • 1 问题背景
  • 2 前言
  • 3 解决方案
    • 3.1 核心思路
    • 3.2 数据库设计
    • 3.3 下一次发送webhook的时间算法
    • 3.3 详细设计
  • 4 延申思考

1 问题背景

作为一个收单系统,当获取到一笔交易的支付结果时,就需要发送一个webhook消息给电商系统。电商系统收到webhook消息后,会翻转支付状态。如果发送webhook失败,那么电商系统无法拿到webhook消息从而翻转支付状态,那么就会有问题。对于买家而言则是明明已经支付了,在电商系统这里却未支付,买家可能会要求卖家退款或者取消订单。对于卖家而言则是明明收到款了,但是电商系统那里却显示为未支付,这样减少了支付转化率以及降低了买家的顾客体验。

2 前言

本博客讲述的是生产环境真实遇到的场景,不是那种八股文或者小打小闹的demo。

3 解决方案

3.1 核心思路

采用XXL-JOB定时调度+最大重试次数+重试频率递减的重试机制

3.2 数据库设计

支付单的表需要加入3个字段:

  • is_webhook:是否已经成功发送webhook
  • retry_times:已重试的次数
  • next_retry_webhook_time:下一次发送webhook的时间

3.3 下一次发送webhook的时间算法

考虑到如果第1次发送失败,那么紧接着立刻发送重试的成功率不会太高,因此设计一个重试频率递减的算法。

下一次发送 webhook 的时间 = (已重试的次数+1) * 5min + 当前时间

3.3 详细设计

  1. 使用XXL-JOB定时调度,每6min调度一次。调度间隔可以根据实际情况调整,不一定是6min
  2. 最大重试次数可以采用apollo配置动态获取,由于改最大次数也不会经常改变,也可以采用硬编码实现。下一次重新发送webhook的时间 = (已重试的次数+1) * 5min + 当前时间,实现频率递减的效果。
  3. 查询待重试发送webhook的支付单。查询条件必须是未发送webhook成功,且已重试次数小于最大重试次数,且下一次发送webhook的时间要小于当前时间。由于要用到下一次发送webhook的时间,因此需要给该字段加索引
  4. 如果重试次数用完了,可以手动重置重试次数
  5. 不论发送成功还是发送失败,都要打上关键日志

4 延申思考

本文讲述的解决方案与Nacos的健康检查有异曲同工之处。

Nacos同样是用异步线程执行定时任务,每隔5秒就会扫描注册上来的实例。Nacos会判断实例上次发送心跳的时间,到当前时间差了多少,如果超过15s则标记该实例,再过15s仍然没有发来心跳,Nacos则剔除该实例。

本文解决方案同样采用定时任务,每隔6min扫描需要重试发送webhook的支付单。当未成功发送webhook,且重试次数未达到最大,且下一次发送webhook时间到达了,则会开始重试发送webhook。同时本文采用了一个重试频率递减的重试机制。

你可能感兴趣的:(解决方案,大数据)