什么是接口幂等性

2021-02-24 18:20发布


7.1. 什么是接口幂等性

幂等,指的是任意多次执行所产生的影响均与一次执行的影响相同

幂等方法,可以是相同参数重复执行,并能获得相同结果的方法,这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变

7.1.1 业务 CRUD

其中的读取 Retrieve 和删除 Delete 是天然幂等的,受影响的就是创建 Create 和更新 Update

7.1.2 HTTP 协议

HTTP 中有各种各样的请求方法,其中幂等的方法有

  • GET

  • HEAD

  • PUT

  • DELETE

非幂等方法有:

  • POST


7.2、幂等性应用场景

接口的幂等性设计,也有很多业务的应用场景

业务中考虑幂等性的地方一般是接口的重复请求,会有以下几种常见场景导致接口重复被请求:

  • 前端重复提交:提交订单,用户快速重复点击多次,造成后端生成多个内容重复的订单

  • 接口超时重试:对于第三方调用接口,为了防止网络抖动或其他原因导致丢失,接口一般会设计成超时重试多次

  • 消息重复消费:防止 MQ 中的消息被重复消费

  • 金融交易业务:防止支付请求可能被重复发送

7.3、接口幂等性实现方式

7.3.1 前端简单拦截

控制前端的组件可见性来拦截重复提交

  • 防止表单重复提交、不可点击的方案(按钮置灰、隐藏按钮)

7.3.2 Token 机制

利用 Token + Redis 验证来防止重复提交

  • Client 没有 token,请求 Server,获取 token

  • Server 生成 token,并缓存到 Redis 中,返回 token 给 Client

  • Client 带着 Token(放到报文头),请求 Server 进行业务操作

  • Server 首先验证 Token,在 Redis 查询该 Token 是否存在

    • Redis 有 Token,说明是第一次提交,执行业务,并删除 Token

    • Redis 没 Token,说明是重复提交,不执行业务,返回拒绝请求

可以看到,生成的每一次 Token 的有效期都是一次业务未执行到执行完期间,每一次业务操作对应着一个唯一的 Token

7.3.3 Redis 缓存唯一序列号

比起 Token,可以直接把业务相关的信息缓存到 Redis 中,报文头部不需要存东西,对于客户端来说更轻量级

例如,一次支付请求可以这么做:

  • Server 首先验证进来的支付请求,检查缓存是否有订单 ID

  • Redis 里面没有订单 ID,缓存支付请求的订单 ID ,然后去做相应的业务操作

    • 无论支付操作成功还是失败,在支付操作结果返回后,在 Redis 里删除该订单 ID 的 Key

  • Redis 里面有订单 ID,直接返回重复请求的提示结果,支付终止

所以,基于 Redis 来说,可以这么存储:

  • Key:唯一序列号,生成唯一的 Key 可以借助雪花算法和自定义的字段组合来生成

  • Value:任何想填的信息,比如订单的相关信息等

例如,对于 KafKa 的重复消费,也可以使用这样的方式来做,那之前,先看看 Kafka 的重复消费是指的什么

KafKa 的消费过程是这样的

  • 生产者生产一个消息,给 Kafka

  • Kafka 格式化生产消息,也就是每个消息会有一个 offset,把数据格式化成 msg | offset 这样的形式

  • 消费者与 ZK 协调,ZK 记录消费者当前消费到的消息的 offset,消费者会从 ZK 指定的 offset 顺序消费

  • 消费者会定期提交一次当前消费的 offset,而不是消费一条就提交一次