幂等性方案

1.什么是幂等性

幂等:是一个数学与计算机的概念,在编程领域中,一次幂等操作:用相同参数重复执行,并能获得相同结果的。

任意多次执行所产生的影响均与一次执行的影响相同,这是幂等性的核心特点。

2.业务场景

  • 前端重复提交:提交订单,用户因网络延迟连续、快速提交造成后端生成多次重复的记录。
  • 消息重复消费:MQ消息中间件,消息重复消费。
  • 接口超时重试:对于给第三方调用的接口,为了防止网络抖动或其他原因造成请求重试,导致一个请求提交多次。

3.接口幂等性

说明:对于业务中需要考虑到幂等性操作,一般都是接口的重复请求,一个请求因特殊原因被多次请求。其中某一次处理开始或者成功了,我虽然又接收到了消息,但是这时我不处理了,即保证接口的 幂等性

接口幂等性:指的是用户对同一操作发起了一次或多次请求的结果是一样的,不会新多次请求而对系统产生影响。这类问题多发生于接口的新增insert和修改update操作,查询select与删除delete操作具有天然幂等性,逻辑删除也具备幂等性。

  • insert操作:多次请求插入多条数据
  • update操作:计算式不具备幂等性 update goods set number=nember-1 where id=1 非计算式具备幂等性 update goods set number = 1 where id=1

3.1 实现方式

没有最优的方案只有最适合的:

实现接口幂等的方式多种,我们在判断业务需要幂等操作时要结合具体情况使用。

防重token机制:对于需要幂等性操作的接口,在进入页面后会请求一个token值,在用户提交表单时会携带服务端返回的token标识,该token在同一次请求下不会发生改变。

流程如下:

  • 服务端提供生成唯一token的接口,并将该token存放在redis中。
  • 携带着token调用业务接口,业务内部会进行token校验。
  • 业务通过查询redis判断token是否存在,存在就删除token继续执行业务(保证原子操作)。
  • 判断token不存在,那么返回给客户端重复业务操作。

· 通过 Token 的机制可以解决重复下单,重复提交等场景。

唯一约束性: 利用数据库中唯一索引的约束进行去重,适用于insert操作时的幂等性,能保证一张表中只能存在一条带该唯一性约束的数据。需要注意的是,该约束字段一般来说使用分布式 ID 充当主键,这样才能能保证在分布式环境下 ID 的全局唯一性。

分布式ID的生成可以使用雪花算法、redis原子自增等方式生成唯一。

流程如下:

  • 客户端调用创建请求接口
  • 服务端执行业务,生成一个分布式ID,将该ID作为唯一约束字段的数据执行SQL操作。
  • 插入成功表示没有重复调用,如果抛出异常则表示存在该条数据,返回错误信息给客户端。

状态机:很多的业务是有一个业务流转状态的,每个状态都有前置和后置状态、最终状态。比如审批流程状态,订单状态。以订单为例,*已支付* 的前置状态只能是未支付 取消 的前置状态只能是 未支付 通过这种状态的变更我们可以控制幂等性操作。假设当前状态是已支付,这时候如果支付接口又接收到了支付请求,我们更新订单的状态,订单条件必须是未支付 ,但实际不是,则会抛异常或拒绝此次处理,达到幂等性

乐观锁:乐观锁方案一般只能适用于执行更新操作的过程,我们可以提前在对应的数据表中多添加一个字段version,充当当前数据的版本标识。每次对该条数据执行更新时,都会将该版本标识作为一个条件,值为上次待更新数据中的版本标识的值。它的执行流程与token机制类似,需要先获取数据的版本号,不推荐。

UPDATE table_name SET stock = stock-1,version = version+1 WHERE id = 1 AND version = 2

上面 WHERE 后面跟着条件 id = 1 AND version = 2 被执行后,id=1 的 version 被更新为 3,所以如果重复执行该条 SQL 语句将不生效,因为 id = 1 AND version = 2 的数据已经不存在,这样就能保正更新的幂等性,多次更新对结果不会产生影响。

3.2 幂等性的影响

幂等性一方面为了保证接口的安全性,从而保证了数据的一致性,另一方面也增加了业务逻辑的复杂性,增加了额外控制幂等的业务逻辑,复杂化了业务功能。所以在使用时候需要考虑是否引入幂等性的必要性,根据实际业务场景具体分析,除了业务上的特殊要求外,一般情况下不需要引入的接口幂等性。

3.3 结论

一个API拥有幂等能力的话,调用发起方就可以很安全的进行重试。这符合我们普遍的要求,也是开发当中很常见也很重要的一个需求,尤其是支付订单等与金钱挂钩的服务,保证接口幂等性尤其重要。一个接口要不要保证幂等的条件是需不需要保证该资源的唯一性

  • 类似于前端重复提交、重复下单的场景,可以通过 Token 与 Redis 配合的“防重 Token 方案”实现更为快捷。
  • 对于更新订单状态等相关的更新场景操作,使用“乐观锁”实现更为简单。
  • 对于下单,注册等存在唯一约束的,可以使用“唯一索引约束”的方式实现。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇