并发时重复请求导致的异常处理方案

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   作者:朱灿奕