乐趣区

关于java:Spring-Boot-接口幂等插件使用

幂等概述

  • 幂等性本来是数学上的概念,即便公式:f(x)=f(f(x)) 可能成立的数学性质。用在编程畛域,则意为对同一个零碎,应用同样的条件,一次申请和反复的屡次申请对系统资源的影响是统一的。
  • 幂等性是分布式系统设计中非常重要的概念,具备这一性质的接口在设计时总是秉持这样的一种理念: 调用接口产生异样并且反复尝试时,总是会造成零碎所无奈接受的损失,所以必须阻止这种景象的产生
  • 实现幂等的形式很多,目前基于申请令牌机制适用范围较广。其核心思想是为每一次操作生成一个唯一性的凭证,也就是 token。一个 token 在操作的每一个阶段只有一次执行权,一旦执行胜利则保留执行后果。对反复的申请,返回同一个后果(报错)等。参考《幂等性浅谈》

幂等解决实现

退出依赖

<dependency>
    <groupId>com.pig4cloud.plugin</groupId>
    <artifactId>idempotent-spring-boot-starter</artifactId>
    <version>0.0.1</version>
</dependency>

配置 Redis 链接

  • 默认状况下,能够不配置。实践是反对 redisson-spring-boot-starter 全副配置
spring:
  redis:
    host: 127.0.0.1
    port: 6379

接口

@Idempotent(key = "#key", expireTime = 10, info = "请勿反复查问")
@GetMapping("/test")
public String test(String key) {return "success";}

测试

  • 10 个独立线程申请

  • 执行查看后果,10 个申请只会有一个胜利

  • 查看后盾异样报错,9 个异样报错满足预期

idempotent 注解阐明

  • key: 幂等操作的惟一标识,应用 spring el 表达式 用 #来援用办法参数。 可为空则取以后 url + args 做申请的惟一标识
  • expireTime: 有效期 默认:1 有效期要大于程序执行工夫,否则申请还是可能会进来
  • timeUnit: 工夫单位 默认:s(秒)
  • info: 幂等失败提示信息,可自定义
  • delKey: 是否在业务实现后删除 key true: 删除 false: 不删除

幂等解决设计原理

流程设计参考

  • 1. 申请开始前,依据 key 查问 查到后果:报错 未查到后果:存入 key-value-expireTime key=ip+url+args
  • 2. 申请完结后,间接删除 key 不论 key 是否存在,间接删除 是否删除,可配置
  • 3.expireTime 过期工夫,避免一个申请卡死,会始终阻塞,超过过期工夫,主动删除 过期工夫要大于业务执行工夫,须要大略评估下;
  • 4. 此计划间接切的是接口申请层面。
  • 5. 过期工夫须要大于业务执行工夫,否则业务申请 1 进来还在执行中,前端未做遮罩,或者用户跳转页面后再回来做反复申请 2,在业务层面上看,后果仍旧是不合乎预期的。
  • 6. 倡议 delKey = false。即便业务执行完,也不删除 key,强制锁 expireTime 的工夫。预防 5 的状况产生。
  • 7. 实现思路:同一个申请 ip 和接口,雷同参数的申请,在 expireTime 内屡次申请,只容许胜利一次。
  • 8. 页面做遮罩,数据库层面的惟一索引,先查问再增加,等解决形式应该都解决下。
  • 9. 此注解只用于幂等,不用于锁,100 个并发这种压测,会呈现问题,在这种场景下也没有意义,理论中用户也不会呈现 1s 或者 3s 内手动发送了 50 个或者 100 个反复申请, 或者弱网下有 100 个反复申请;

总结

  • pig-mesh/pig
  • pig-mesh/idempotent-spring-boot-starter

退出移动版