接口幂等性这事以前我想的有些简单了

在讨论接口支持幂等性时,我们往往默认它"相同参数经过多次调用后对系统结果的一致性"。然而,在我最近的工程中,这个概念似乎并不完全正确。

以交易系统中的下单为例,用户下单购买商品,系统需要扣款。付款方式有1. 用户自己的积分资产 2. 从三方支付系统(比如支付宝)扣钱然后发货,用户收货成功后,给用户再发奖励积分。

这里涉及到多个幂等场景,例如:

  1. 用户点击下单,防止用户重复下单,下单系统要支持幂等。

  2. 下单系统调积分系统,防止两边系统不一致,重试造成多扣,积分系统需要支持幂等。

  3. 下单系统调用三方支付系统,防止两边系统不一致,重试造成多扣,积分系统需要支持幂等。

  4. 用户确认收货后,给用户发放奖励积分。一笔交易发放一次奖励积分,不能多发。

为了专注问题讨论,现在我们来看积分系统怎么支持幂等性。接口支持幂等时,指的是使用相同参数无论调用多少次,对系统造成的结果是一致的。这里面包含两层含义

  1. 接口调用方来定义相同请求参数

  2. 接口提供方对相同请求参数, 实现相同的结果。

一个接口的请求参数通常很多,为了简化相同参数的定义,通常约定一个幂等号,即多次请求中的幂等号一致,接口提供方认为是同一请求。

接口实现方的主要操作

增加幂等号查询记录判断来避免重复请求,当然我们还会增加锁控制以及数据库层面的幂等号唯一性设计,来确保幂等号的 不重复。上述方案看似解决了问题。在实际应用中,仅在正常情况下接口返回了正确的结果,并不意味着所有异常场景下都不会出现问题,看下以下特殊场景

场景 接口提供方 接口提供方返回结果 调用方收到的结果 是否需要重试
1 操作成功 成功 成功 不需要
2 操作成功 成功 失败(网络异常导致超时) 需要
3 操作失败(业务异常,比如积分不足) 失败(业务异常) 失败 不需要
4 系统异常 失败 失败 需要
5 奖励积分操作失败(当日限额) 失败 失败 不需要

场景3

因为是业务异常,重试是徒劳的,所以调用方不需要重试 。

但是调用方不讲武德,仍旧重试。比如第一次返回的是积分不足 。但是隔了一段时间,调用方还来调用,这时候用户积分够了,按照上述流程,这次会重试成功,显然这接口满足不了幂等性。

所以我们在第一次处理时,必须要把处理结果记录下,即使并没有发生真实扣减。这地方的迷惑性在于幂等号,使用幂等号来代替使用相同参数,但是不同时间,相同幂等号对应的服务提供方在不同时刻的资源是不一致的,这些资源也可以理解为入参。所以要以首次请求为准。经过调整后,我们实现了幂等。

但是现在遇到场景5

用户下单成功后,奖励积分给用户。这个在业务上是一个必须达成的操作。但是调用积分系统时,触发了当日限额, 无法发放成功。从积分系统的接口设计角度来说,会一直幂等返回失败。但是下单发放积分奖励的系统不这样认为,他认为这是一个必须达成的操作, 所以会一直重试,这时候即使当日限额提升了,接口因为幂等原因,也无法发放成功。

所以调用方必须要换用幂等号,才能实现操作成功。但是这个场景,换幂等号风险很高,因为原本可以用订单号来做幂等号,如果换幂等号,很容易资损,调用方必须要设计一个单个订单下只有一个成功的幂等号。从整体设计来看,积分系统接口严格遵循了幂等设计,把复杂留给了调用方,但是整个流程并没有严格幂等,并引入了更复杂的处理。

综合上述分析,我们可以看到,为了应对这种场景,在设计上其实可以采取一些折衷措施。

  1. 结果为成功时,幂等防止重复请求

  2. 结果为失败时,允许重试,服务提供方重新处理流程,资源允许情况下,会将结果处理为成功。

这样的设计违背了幂等性的定义,但从实际工程的角度出发,它可以有效地解决部分场景问题。

所以 如果你是积分系统的开发者,你会设计成什么样呢?

相关推荐
禅思院44 分钟前
AI对话前端从入门到崩溃:一个长对话引发的五层优化战争【引子】
前端·面试·架构
带刺的坐椅1 小时前
用 ChatModel 构建 LLM 驱动的 Java 应用
java·ai·llm·solon·rag·chatmodel
赫媒派1 小时前
Gin 12年零破坏API,架构哲学如何练成?
后端·go·gin
fliter2 小时前
Arborium:把 tree-sitter 语法高亮打包成 Rust 文档生态的基础设施
后端
张三丰22 小时前
不会写代码的高管用Claude Code两天上线新程序,工程师接手后发现:一个Bug,让AI一天烧掉一个月服务器费!
后端
Ai拆代码的曹操2 小时前
从一条转账 SQL 到分布式事务:5 种方案的全方位对比与实战
后端
林希_Rachel_傻希希2 小时前
web性能之相关路径——AI总结
前端·javascript·面试
掘金小豆2 小时前
Spring 事务失效的 6 大场景,你踩过几个?
后端·spring·面试
不好听6132 小时前
从零搭建一个 RAG 语义搜索系统 —— DEMO的初始阶段
javascript·面试·llm
im_lanny2 小时前
Agent = Model + Harness:决定 AI 智能体上限的,往往不是模型而是“装具”
后端