本文介绍接口幂等性含义以及接口幂等性保证方案。

什么是幂等?

幂等操作指任意多次执行所产生的影响与一次执行的影响相同,可以保证重复调用的结果和单次调用的结果一致。

使用幂等的场景

1、前端重复提交

用户注册,用户创建商品等操作,前端都会提交一些数据给后台服务,后台需要根据用户提交的数据在数据库中创建记录。如果用户不小心多点了几次,后端收到了好几次提交,这时就会在数据库中重复创建了多条记录。这就是接口没有幂等性带来的 bug。

2、接口超时重试

对于给第三方调用的接口,有可能会因为网络原因而调用失败,这时,一般在设计的时候会对接口调用加上失败重试的机制。如果第一次调用已经执行了一半时,发生了网络异常。这时再次调用时就会因为脏数据的存在而出现调用异常。

3、消息重复消费

在使用消息中间件来处理消息队列,且手动 ack 确认消息被正常消费时。如果消费者突然断开连接,那么已经执行了一半的消息会重新放回队列。当消息被其他消费者重新消费时,如果没有幂等性,就会导致消息重复消费时结果异常,如数据库重复数据,数据库数据冲突,资源重复等。

解决方案

基于 MySQL 实现

这种实现方式是利用 MySQL 唯一索引的特性。

示意图如下:

基于 MySQL 实现幂等

具体流程步骤:

  1. 建立一张去重表,根据请求的某个字段建立唯一索引
  2. 请求服务端,服务端插入信息这张去重表中(包含了去重表中定义的唯一索引的字段)
  3. 如果插入成功,证明表中没有这次请求的信息,则执行后续的业务逻辑
  4. 如果插入失败(唯一索引冲突 DuplicateKeyException),则代表已经执行过当前请求,直接返回

基于 Redis 实现

这种实现方式是基于 SETNX 命令实现的。

SETNX key value:将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不做任何动作。

该命令在设置成功时返回 1,设置失败时返回 0。

示意图如下:

基于 Redis 实现幂等

具体流程步骤:

  1. 客户端先请求服务端,会拿到一个能代表这次请求业务的唯一字段
  2. 将该字段以 SETNX 的方式存入 Redis 中,并根据业务设置相应的超时时间
  3. 如果设置成功,证明这是第一次请求,则执行后续的业务逻辑
  4. 如果设置失败,则代表已经执行过当前请求,直接返回

参考

https://zhuanlan.zhihu.com/p/345512692