Skip to content

接口幂等性

本文阐述接口幂等性的核心概念与实现方案。幂等性指多次执行产生相同结果的特性,在分布式系统中尤为重要。涵盖接口重复提交、消息重试等典型应用场景,详细解析数据库唯一主键、乐观锁、Token令牌、请求序列号四种技术方案,对比各方案优缺点及适用场景,为构建可靠分布式系统提供实践指导。

什么是幂等性

幂等是一个数学与计算机学概念,在数学中某一元运算为幂等时,其作用在任一元素两次后会和其作用一次的结果相同

幂等函数或幂等方法是指可以使用相同参数重复执行,并能获得相同结果的函数。

这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变

接口幂等性

HTTP/1.1中,对幂等性进行了定义:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)

即第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用。

这里的副作用是不会对结果产生破坏或者产生不可预料的结果。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。

需要幂等性的场景

  1. 前端重复提交表单
  2. 用户恶意刷单
  3. 接口超时重复提交
  4. 消息重复消费

使用幂等性最大的优势在于使接口保证任何幂等性操作,免去因重试等造成系统产生的未知的问题。

引入幂等性后对系统的影响

幂等性是为了简化客户端逻辑处理,能放置重复提交等操作,但增加了服务端的逻辑复杂性和成本

  1. 把并行执行的功能改为串行执行,降低了执行效率
  2. 增加了额外控制幂等的业务逻辑,复杂化了业务功能

幂等性方案

1、数据库唯一主键

需要生成全局唯一主键 ID

采用分布式 ID 充当主键,保证在分布式环境下 ID 的全局唯一性

常见方案:

  • 雪花算法
  • 数据库号段模式
  • Redis自增

2、数据库乐观锁

需要数据库对应业务表中添加额外字段

一般只能适用于执行更新操作的过程,加一个字段标识当前版本,每次更新时判断

常见方案:

sql
UPDATE my_table SET price=price+50,version=version+1 WHERE id=1 AND version=5

3、Token 令牌

  • 需要生成全局唯一 Token
  • 需要使用 Redis

调用接口前先获取全局唯一Token,再使用此Token调用接口,保证每次请求的Token是唯一的

wiki
注意,在并发情况下,执行 Redis 查找数据与删除需要保证原子性,否则很可能在并发下无法保证幂等性。
其实现方法可以使用分布式锁或者使用 Lua 表达式来注销查询与删除操作

4、请求序列号

  • 调用者需传递唯一序列号
  • 需要使用 Redis

请求时候附带一个短时间内唯一不重复的序列号和下游认证ID,上游服务器收到请求信息后拿取该 序列号 和下游 认证ID 进行组合,形成用于操作 Redis Key,然后到 Redis 中查询是否存在对应的 Key 的键值对

  • 如果存在说明已经对该请求进行了处理

  • 如不存在,就以该 Key 存入Redis,处理业务逻辑。

简单来说,就是存一下已操作请求的唯一标识,再遇到同样请求不予处理

总结

方案适用性优点缺点
数据库唯一主键增、查、改、删全局唯一性,数据库 ACID 特性可能成为性能瓶颈,需要额外配置和调优
数据库乐观锁避免悲观锁性能开销,版本号比对仅适用于更新操作,版本冲突需要处理
Token 令牌增、查、改、删易于实现,外部调用方提供标识需要确保 Redis 操作原子性,管理 Token
请求序列号增、查、改、删相对轻量,不依赖数据库特殊支持需要确保 Redis 操作原子性,调用方负担

Last updated: