并发时重复请求导致的异常处理方案
1、(建议)数据表中建立唯一索引
其实不只是唯一索引,在设计表的时候就应该要把索引建立,然后再根据场景来看哪些需要添加索引
2、接口请求排重检查
pai 提供了默认的排重检查 但是需要配置
<dependency>
<groupId>cn.flyrise</groupId>
<artifactId>pai-common-interceptor</artifactId>
<version>${pai.version}</version>
</dependency>
pai:
repeat:
#开关
enable: true
#支持内存模式和redis模式,内存:local,redis:redis
type: redis
#缓存的时间,单位是秒
time-to-live: 5
在controller上添加注解 @RepeatSubmit
@RepeatSubmit
@PreAuthorize("@conspms.hasPermission('ent_admin:cons_application')")
@SysLog(action = ConsoleConstants.INSTALL_APP)
@ApiOperation("套件安装")
@PostMapping("/install")
public Reply install(@Validated @RequestBody InstallAppRequest request) {
runService.install(request);
return Reply.success();
}
3、支持自定义的排重配置
1、调整一下配置
2、实现MessageDuplicateChecker排重逻辑
3、注入RepeatSubmitInterceptorImpl拦截器
pai:
repeat:
#开关
enable: true
#自定义的模式,type改为 custom
type: custom
#缓存的时间,单位是秒
time-to-live: 5
实现排重逻辑
public class MessageRedisDuplicateChecker implements MessageDuplicateChecker {
/**
* 一个消息ID在内存的过期时间:15秒.
*/
private final Integer timeToLive;
private static final String CACHE_MESSAGE = "message:checker:";
private final RedisTemplate redisTemplate;
public MessageRedisDuplicateChecker(Integer timeToLive, RedisTemplate redisTemplate) {
this.timeToLive = timeToLive;
this.redisTemplate = redisTemplate;
}
public MessageRedisDuplicateChecker(RedisTemplate redisTemplate) {
this.timeToLive = 5;
this.redisTemplate = redisTemplate;
}
@Override
public boolean isDuplicate(String messageId) {
Boolean success = redisTemplate.opsForValue().setIfAbsent(CACHE_MESSAGE + messageId, messageId, timeToLive,
TimeUnit.SECONDS);
return !success;
}
}
声明拦截器
@Bean("repeatSubmitInterceptor")
@ConditionalOnProperty(prefix = "pai.repeat", name = "type", havingValue = "custom", matchIfMissing = true)
public RepeatSubmitInterceptor custom() {
StaticLog.info("====启用custom排重====");
Integer timeToLive = paiRepeatProperties.getTimeToLive();
return new RepeatSubmitInterceptorImpl(new MessageRedisDuplicateChecker(timeToLive,redisTemplate));
}
文档更新时间: 2024-05-28 09:24 作者:朱灿奕