一、前言
接口幂等就是对一个接口执行重复的多次请求,与一次请求所产生的结果是相同的。对数据库的查询和删除是天然幂等的,更新操作在大多数场景下也是天然幂等。插入大多数情况下都是非幂等的,除非利用数据库的唯一索引来保证数据不会重复保存。
二、为什么需要幂等
1.超时重试
当发起一次RPC请求时,难免会因为网络不稳定而导致请求失败,一般遇到这样的问题我们希望能够重新请求一次,正常情况下没有问题,但有时请求实际上已经发出去了,只是在请求响应时网络异常或者超时,此时,请求方如果再重新发起一次请求,那被请求方就需要保证幂等了。
2.异步回调
异步回调是提升系统接口吞吐量的一种常用方式,很明显此类接口一定是需要保证幂等性的。
3.消息队列
现在常用的消息队列框架,比如:Kafka、RocketMQ、RabbitMQ在消息传递时都会采取At least once原则(也就是至少一次原则,在消息传递时,不允许丢消息,但是允许有重复的消息),既然消息队列不保证不会出现重复的消息,那消费者自然要保证处理逻辑的幂等性了。
三、实现幂等的关键因素
关键因素1
幂等唯一标识可以叫它幂等号或者幂等令牌或者全局ID,总之就是客户端和服务端一次请求的唯一标识,一般情况下由客户端来生成,也可以让第三方来统一分配。
关键因素2
有了唯一标识以后,服务端只需要确保这个唯一标识只被使用一次即可,一种常见的方式就是利用数据库的唯一索引。
四、代码实现
1.添加依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.自定义注解
package com.example.aopdemo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义幂等注解
*/
@Target(value = ElementType.METHOD)
@Retention(RetentionPolic