避免重复扣款:分布式支付系统的幂等性原理与实践

news2024/9/23 21:20:16

这是《百图解码支付系统设计与实现》专栏系列文章中的第(6)篇。

本文主要讲清楚什么是幂等性原理,在支付系统中的重要应用,业务幂等、全部幂等这些不同的幂等方案选型带来的收益和复杂度权衡,幂等击穿场景及可能的严重后果。

这也是支付公司面试的必考题目之一。

1. 什么是幂等性原理

幂等性是一个数学和计算机科学术语,用于描述无论操作执行多少次,都产生相同结果的属性。在软件行业,应用极其广泛,当我们说一个接口支持幂等时,无论调用多少次,对系统造成的结果是一致的

注意这里说的“对系统造成的结果是一致的”是指系统内部数据或状态的变更,不是指返回值。不同的系统设计,返回值可能是不一样的。

举个例子,你在淘宝免密支付10元,淘宝针对这笔订单调用支付宝支付接口进行支付,无论是调用1次,还是调用100次,最终只扣了你10元。但是第二次有可能返回“重复请求”,也有可能返回“支付成功”,这个取决于接口设计。也就是支付宝内部只扣了你10元,但是接口可能返回给商户是是不同的结果。

我个人倾向于方案一,如果等幂等,就返回:重复请求。减少误解,虽然两种方案中系统都只扣了一次钱。

2. 为什么幂等性在支付系统中极其重要

支付系统必须以最高的可靠性和准确性处理交易,这对于用户信任至关重要。如果一个支付系统不能保证幂等性,可能会导致多次扣除同一笔费用,引发用户不满和法律责任,严重时就会有舆情风险,甚至会被吊销牌照。

一般情况下,支付系统的幂等性能力要求比电商系统要求更高,如果用户在电商下单多了,只要没有支付,用户还是可以忍受的,但一旦多扣了用户的钱,后果就会比较严重。

这也是为什么幂等性会是支付系统招人的面试必考题目之一。

3. 支付系统中应用幂等性的场景

幂等是针对重复请求的,支付系统一般会面临以下几个重复请求的场景:

  1. 用户多次点击支付按钮:在网络较差或系统过载情况下,用户由于不确定交易是否完成而重复点击。
  2. 自动重试机制:系统在超时或失败时重试请求,可能导致同一支付多次尝试。
  3. 网络数据包重复:数据包在网络传输过程中,复制出了多份,导致支付平台收到多次一模一样的请求。
  4. 异常恢复:在系统升级或崩溃后,未决事务需要根据已有记录恢复和完成。内部系统重发操作。

4. 幂等解决方案

4.1. 业务幂等

所谓业务幂等,就是由各域自己把唯一性的交易ID作为数据库唯一索引,这样可以保证不会重复处理。

在数据库前面可以加一层缓存来提高性能,但是缓存只用于查询,查到数据认为就返回幂等成功,但是但不到,需要尝试插入数据库,插入成功后再刷新数据到缓存。

为什么要使用数据库的唯一索引做为兜底,是因为缓存是可能失效的。

在面临时经常有同学只回答到“使用redis分布式锁来实现幂等”,这是不对的。因为缓存有可能失效分布式锁只是用于防并发操作的一种手段,无法根本性解决幂等问题,幂等一定是依赖数据库的唯一索引解决。

大部分简单的支付系统只要有业务幂等基本也够用了。

4.2. 通用幂等组件

每个域都要做幂等处理,那就单独出一个独立的幂等组件,各子业务系统通过引用这个公共JAR包解决。

适用场景:应用部署不太多的时候。如果应用非常多,独立幂等DB的连接池就不够用。

这个时候,可以把幂等组件的代码共用,但是幂等数据库表使用业务系统的DB资源。解决独立幂等DB导致的连接数不够用的场景。

4.3. 通用幂等服务

解决DB连接数不够用的第二个解决方案:幂等组件服务化。这样的坏处就是复杂度和耗时都会增加。

4.4. 全局幂等

在多机房部署情况下,需要解决机房之间的幂等服务。这就使用到了全局幂等概念。

所谓全局幂等,就是多个机房共用一份幂等数据,这里面涉及的技术比较复杂,后面单独开一个章节讲。除了极少数全球部署的多活支付系统都用不上。

4.5. 通用幂等数据库表设计

核心字段:

uniqueKey:幂等主键,由各应用自定义,需要保证全局唯一性使用这个uniqueKey做hash后分库分表。比如商户的收单ID,上游的ID等。

appName: 应用名称,比如收单,支付等。

siteId:站点ID

extInfoMap:扩展字段,由各应用自定义,比如保存我方单号。

4.6. 方案选型建议

简单的支付系统,只需要使用业务幂等就够。

中型的支付系统,推荐使用通用幂等组件。这样方便运维。

全局幂等方案只有极少数公司会考虑。

5. 分布式场景下实现幂等性的挑战及应对

分布式支付系统面临的幂等性挑战核心有两点:

  1. 如何保证分布于不同地理位置数据中心的系统数据的一致性。
  2. 幂等数据和业务数据跨库事务一致性。比如幂等已经入库成功,但是业务数据库入库失败。

为了解决这些挑战,可以采取以下解决方案:

  1. 使用全局唯一的交易ID,跟踪每次支付请求,防止重复处理。
  2. 幂等住了之后,还需要继续查询业务数据,如果查询失败,仍然执行业务操作。
  3. 构建强大的状态机推进能力,严格定义事务各个状态的转换。
  4. 幂等服务的高可靠性。

6. 幂等被击穿场景及可能的严重后果

尽管有了上述措施,幂等性仍然可能因为以下原因失效:

  1. 在分布式系统中,由于同步延迟,导致多个节点未能即时识别重复请求。
  2. 请求流量切换。原本应该路由A机房的数据路由到了B机房,但是B机房的幂等数据缺失。
  3. 生成全局唯一ID的算法出现故障或人为变更,同一笔业务可能出现了2个业务ID。

在支付系统中,只要幂等被击穿,基本上都会出现资损事件。有时候是用户资损,有时候是平台资损。曾经碰到一个真实案例,上游域把某个幂等字段组成规则的取值变了,但是下游不知道,导致下游幂等失败,对同一笔业务处理了2次,直接资损数十万美金。

7. 结束语

幂等性是分布式支付系统的基本要求,对于确保交易的正确性和避免重复扣费至关重要。除开支付系统外,很多互联网应用基本上都需要有幂等能力。

有机会再单独讲讲全局幂等。

传送门

支付系统设计与实现是一个专业性非常强的领域,里面涉及到的很多设计思路和理论也可以应用到其它行业的软件设计中,比如幂等性,加解密,领域设计思想,状态机设计等。

在《百图解码支付系统设计与实现》的知识宇宙,每一篇深入浅出的文章都是一颗既独立但又彼此强关联的星球,有必要提供一个传送门以便让大家即刻到达想要了解的文章。

专栏地址百图解码支付系统设计与实现

领域相关

基本概念与概要设计:跟着图走,学支付:在线支付系统设计的图解教程

收单结算设计:支付交易的三重奏:收单、结算与拒付在支付系统中的协奏曲

技术专题

与数据库自增ID不同的业务ID:交易流水号的艺术:掌握支付系统的业务ID生成指南

签名验签:揭密支付安全:为什么你的交易无法被篡改

加密解密:金融密语:揭秘支付系统的加解密艺术

日志格式设计规范:支付系统日志设计完全指南:构建高效监控和问题排查体系的关键基石

幂等性设计:避免重复扣款:分布式支付系统的幂等性原理与实践

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1368175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sqlmap性能优化

sqlmap性能优化 🎈🎈🎈🎈🎈🎈🎈🎈🎈🎈🎈🎈🎈🎈🎈🎈🌭🌭&#…

【Linux Shell】11. 输入/输出 重定向

文章目录 【 1. 重定向简介 】【 2. 输出重定向 】【 3. 输入重定向 】【 4. Here Document 】【 5. /dev/null 文件 】 【 1. 重定向简介 】 大多数 UNIX 系统命令从终端接受输入并将所产生的输出发送回​​到原来输入的终端。一个命令通常从标准输入的地方读取输入&#xff…

漫谈与人类智能相关数学知识的不足之处

客观地说,没有数学就没有当前的大语言模型、多模态大模型,甚至压根就没有人工智能。对人工智能而言,数学就是“天”!但是,对于人类智能而言,数学虽然起到了很重要的作用,同样也起到了阻碍作用&a…

table嵌套table的样式

文章目录 table嵌套的格式table嵌套表格的样式注意 table嵌套注意事项 table嵌套的格式 tr 内嵌table <table><tr><table></table></tr> </table>td内嵌table <table><tr><td><table></table></td>…

ubuntu创建pytorch-gpu的docker环境

文章目录 安装docker创建镜像创建容器 合作推广&#xff0c;分享一个人工智能学习网站。计划系统性学习的同学可以了解下&#xff0c;点击助力博主脱贫( •̀ ω •́ )✧ 使用docker的好处就是可以将你的环境和别人的分开&#xff0c;特别是共用的情况下。本文介绍了ubuntu环境…

【动态规划】C++算法:446等差数列划分 II - 子序列

作者推荐 【动态规划】C算法312 戳气球 446. 等差数列划分 II - 子序列 给你一个整数数组 nums &#xff0c;返回 nums 中所有 等差子序列 的数目。 如果一个序列中 至少有三个元素 &#xff0c;并且任意两个相邻元素之差相同&#xff0c;则称该序列为等差序列。 例如&#…

Developer Tools for Game Creator 1

插件包含: 持久世界时间管理系统 单击以生成对象或预设 游戏内调试控制台 游戏内事件控制台 控制台管理控制 命令模板脚本 游戏内屏幕截图 低分辨率和高分辨率图像 缩略图生成 移动支持 使用Game Creator Action或拖放来激活和控制组件,无需编码。 通过此资产,您可以获得: …

群晖Synology Drive同步文件时过滤指定文件夹“dist“, “node_modules“

群晖Synology Drive同步文件时过滤指定文件夹"dist", “node_modules” mac用户 安装Synology Drive创建同步任务修改Synology Drive配置 打开/Users/[用户名]/Library/Application Support/SynologyDrive/data/session/[同步任务序号&#xff0c;第一个同步任务就…

Python——python编译器安装教程

1.前往python官网下载安装程序 python官网 python编译器安装程序下载网站 2.找到自己需要的版本&#xff0c;下载对应的安装程序&#xff0c;运行程序 打开安装包&#xff0c;切记要勾选add python 3.9 to PATH 可选择自动安装&#xff08;Install Now&#xff09;或点击自定义…

WPF常用控件-Window

常用属性 这里重点记录一些关键且容易忘记的属性&#xff0c;那些很常用的如Title啥的就不在这里一一说明了。 任务栏按钮 ShowInTaskbar&#xff1a;是否在任务栏中显示应用按钮&#xff0c;默认为True。 层级 Topmost&#xff1a;应用是否始终在所有应用的最上层&#x…

Vue2:通过ref获取DOM元素

一、场景描述 我们在页面的开发过程中&#xff0c;经常需要操作dom元素&#xff0c;来实现我们需要的效果。 以往js中&#xff0c;我们是通过给dom添加id&#xff0c;然后&#xff0c;通过js代码document来获取这个dom 简写代码案例&#xff1a; <h2 id"test"&…

TS 36.211 V12.0.0-下行(6)-同步信号

本文的内容主要涉及TS 36.211&#xff0c;版本是C00&#xff0c;也就是V12.0.0。

第18课 移植FFmpeg和openCV到Android环境

要在Android下从事音视频开发&#xff0c;同样也绕不开ffmpegopencv&#xff0c;不管是初学者还是有一定经验的程序&#xff0c;面临的首要问题就是环境的搭建和库文件的编译配置等问题&#xff0c;特别是初学者&#xff0c;往往会在实际开发前浪费大量的时间来编译ffmpeg及ope…

Qt 三维柱状图 Q3DBar 和 三维条形图中的数据序列 QBar3DSeries

(一) 使用 Q3DBars 图形类和 QBar3DSeries 序列类可以绘制三维柱状图 窗口右侧是用 Q3DBars 和 QBar3DSeries 绘制的三维柱状图&#xff0c;这个图只有一个QBar3DSeries序列&#xff0c;数据是按行存储的&#xff0c;可以有多行。水平方向是行坐标轴和列坐标轴&#xff0c;使用…

C++20新特性解析:深入探讨协程库的实现原理与应用

C20新特性解析&#xff1a;深入探讨协程库的实现原理与应用 一、C20的协程库简介二、C20协程基础知识2.1、协程的基本概念和使用方法2.2、C20中的协程支持2.3、协程与传统线程的对比 三、C20协程库的实现原理四、C20协程库的应用实例总结 一、C20的协程库简介 C20引入了对协程…

.NET学习教程一——.net基础定义+VS常用设置

一、定义 .NET分为.NET平台和.NET框架。 .NET平台&#xff08;厨房&#xff09;.NET FrameWork 框架&#xff08;柴米油盐酱醋茶&#xff09; .NET平台&#xff08;中国移动联通平台&#xff09;.NET FrameWork 框架&#xff08;信号塔&#xff09; .NET平台基于.NET Fra…

AutomationML 学习心得

断断续续地学习AutomationML&#xff08;下面简称AML&#xff09;&#xff0c;其内容很多。概念&#xff0c;术语与与其它建模语言有类似之处&#xff0c;也有不同。同时涉及了一大堆标准。 CAEX&#xff08;IEC 62424&#xff09;COLLADA 几何、动力学模型PLCopen XML 但是&a…

Windows下Redis5+可视化软件下载、安装和配置教程-2024年1月8日

Windows下Redis5下载、安装和配置教程-2024年1月8日 一、下载二、安装三、配置环境四、配置可视化客户端 一、下载 redis是现在是没有对win系统版进行维护的&#xff0c;这个是大神完成的&#xff0c;目前是到5版本&#xff0c;选择Redis-x64-5.0.14.1.zip点击下载 下载地址&…

Python Flask JinJa2 语法介绍与示例讲解

一、概述 Flask是一个轻量级的Python Web框架&#xff0c;支持Jinja2模板引擎。Jinja2是一个流行的Python模板引擎&#xff0c;它可以使用Flask来创建动态Web应用程序。 web 页面一般需要html、css和js&#xff0c;可能最开始学习python web的时候可能这样写&#xff1a; fr…

SpringBoot+策略模式实现多种文件存储模式

一、策略模式 背景 针对某种业务可能存在多种实现方式&#xff1b;传统方式是通过传统if…else…或者switch代码判断&#xff1b; 弊端&#xff1a; 代码可读性差扩展性差难以维护 策略模式简介 策略模式是一种行为型模式&#xff0c;它将对象和行为分开&#xff0c;将行…