浅谈接口幂等性方案

144 阅读2分钟

前言

在我们设计分布式接口时,通常需要考虑如果调用接口失败了,重试再调用该接口会产生怎么样的结果。本篇文章,我们来一起聊聊接口幂等的方案。

什么是幂等性

幂等是一个数学与计算机学概念,在数学中某一元运算为幂等时,其作用在任一元素两次后会和其作用一次的结果相同。放在计算机科学来说,就表示执行一个函数或方法多次,对于系统所产生的影响是一致的。

需要幂等性的场景

一般来说,如果我们设计的接口无法保证幂等,那么则会产生脏数据,严重地甚至会破坏系统的稳定性。需要确保接口幂等主要有以下场景:

  • 最常见的是 RPC 超时,相关的微服务框架会自动重试
  • 前端点击按钮,系统响应时间长没反应,导致用户重复点击按钮多次
  • 消息中间件 MQ 消息重复消费

接口幂等的一般解决方案

方案一:分布式锁

我本人在工作中最常用的方式就是分布式锁,利用 Redis 的 SetNx 特性,当多个线程发起同样的接口调用时,只有抢到锁的线程能够执行接口中的业务逻辑,其余的线程只能够等待锁过期或者锁被释放后才能够执行。这种方案通常会用在 MQ 消费者执行某个长耗时任务的接口中。

方案二:唯一索引

利用 MySQL 唯一索引的特性,数据表中只能存储一条是唯一索引的数据,从而确保了数据写入时的幂等性。但是需要注意的是,主键ID需要保证全局唯一,因此需要采用例如雪花算法等方式来生成主键ID。

方案三:数据库乐观锁

这也是我本人在工作中运用过的一种方案,例如状态机系统:只有状态为「Ready」的任务记录,才能够被更新成「Processing」。

UPDATE `task` SET `status` = 'processing' WHERE `status` = `ready` 

执行这条 SQL 时,MySQL 会乐观地认为状态不会被别人修改。如果多次被执行,那么也只会是状态为 Ready 的那次才会更新成功。

方案四:Token 令牌

这个方案我用得比较少,主要还是利用 Redis 来对请求做去重。

好了,以上就是接口幂等性的一般解决方案,大家学会了吗~