苏眠月|写一个通用的幂等组件,我觉得很有必要( 二 )


使用简单提供通用的幂等组件 , 注入对应的类即可实现幂等 , 屏蔽加锁 , 记录判断等逻辑 。
支持注解除了通过代码的方式来进行幂等的控制 , 同时为了让使用更加简单 , 还需要提供注解的方式来支持幂等 , 使用者只需要在对应的业务方法上增加对应的注解 , 即可实现幂等 。
多级存储需要支持多级存储 , 比如一级存储可以用 Redis 来实现 , 优点是性能高 , 适用于 90%的场景 。 因为很多场景都是为了防止短时间内请求重复导致的问题 , 通过设置一定的失效时间 , 让 Key 自动失效 。
二级存储可以支持 Mysql, Mongo 等数据库 , 适用于时间长或者永久存储的场景 。
可以通过配置指定一级存储用什么 , 二级存储用什么 。 这个场景非常适合用策略模式来实现 。
并发读写引入多级存储势必会涉及到并发读写的场景 , 可以支持两种方式 , 顺序和并发 。
顺序就是先写一级存储 , 再写二级存储 , 读也是一样 。 这样的问题在于性能会有点损耗 。
并发就是多线程同时写入 , 同时读取 , 提高性能 。
幂等执行流程
苏眠月|写一个通用的幂等组件,我觉得很有必要幂等接口幂等接口定义
public interface DistributedIdempotent {/*** 幂等执行* @param key 幂等Key* @param lockExpireTime 锁的过期时间* @param firstLevelExpireTime 一级存储过期时间* @param secondLevelExpireTime 二级存储过期时间* @param timeUnit 存储时间单位* @param readWriteType 读写类型* @param execute 要执行的逻辑* @param fail Key已经存在 , 幂等拦截后的执行逻辑* @return*/T execute(String key, int lockExpireTime, int firstLevelExpireTime, int secondLevelExpireTime, TimeUnit timeUnit, ReadWriteTypeEnum readWriteType, Supplier execute, Supplier fail);}使用方式
/** * 代码方式幂等-有返回值 * @param key * @return */public String idempotentCode(String key) {return distributedIdempotent.execute(key, 10, 10, 50, TimeUnit.SECONDS, ReadWriteTypeEnum.ORDER, () -> {System.out.println("进来了 。。。。 ");return "success";}, () -> {System.out.println("重复了 。。。。 ");return "fail";});}幂等注解使用注解 , 能够让使用更加简单 , 比如我们的事务处理 , 缓存等都使用了注解来简化逻辑 。
幂等的场景也可以定义通用的注解来简化使用难度 , 在需要支持幂等的业务方法上增加注解 , 配置基本信息 。
idempotentHandler 是触发幂等规则后执行的方法 , 也就是我们用代码实现幂等时候的 Supplier fail 参数 。 实现是用的阿里 Sentinel 限流 , 熔断后的处理那套逻辑 。
在幂等的场景下 , 如果是重复执行 , 通常返回跟正常执行一样的结果即可 。
/** * 注解方式幂等-指定幂等规则触发后执行的方法 * @param key */@Idempotent(spelKey = "#key", idempotentHandler = "idempotentHandler", readWriteType = ReadWriteTypeEnum.PARALLEL, secondLevelExpireTime = 60)public void idempotent(String key) {System.out.println("进来了 。。。。 ");}public void idempotentHandler(String key, IdempotentException e) {System.out.println(key + ":idempotentHandler已经执行过了 。。。。 ");}自动区分重复请求代码方式处理幂等 , 需要传入幂等的 Key , 注解方式处理幂等 , 支持配置 Key , 支持 SPEL 表达式 。 这两种都是需要在使用的时候就确定好根据什么来作为幂等的唯一性判断 。
还有一种幂等的场景是比较常见的 , 就是防止重复提交或者网络问题超时重试 。 同样的操作会请求多次 , 这种场景下可以在操作之前先申请一个唯一的 ID , 每次请求的时候带给后端 , 这样就能标识整个请求的唯一性 。


推荐阅读