基于springboot starter,实现接口幂等SDK组件

本文介绍了如何在Spring Boot项目中利用Maven和Redis实现幂等性,通过`idempotent-core`模块提供幂等处理核心逻辑,`idempotent-redis`实现基于Redis的存储。核心接口如`idempotentCheck`确保多次请求结果一致,适用于查询和修改接口防止数据意外变更。
摘要由CSDN通过智能技术生成

一、概述

(一)幂等定义

1. 数学领域的幂等定义

在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“setTrue()”函数就是一个幂等函数,无论多次执行,其结果都是一样的.更复杂的操作幂等保证是利用唯一交易号(流水号)实现。

2. 编程领域的幂等定义

对于一个方法/接口/函数采用同一个数据请求执行任意次数(>=2)而对数据只产生0次或1次变更。则认为该接口/方法/函数具有幂等性

RFC 2616 HTTP 幂等性

(二)为什么需要幂等

早期编程领域主流的架构为单体架构, 接口的调用多为进程内调用.针对每一个接口的调用都存在明确的结果失败OR 成功, 随分布式架构流行越来越多的调用转变成跨网络调用, 受网络的稳定性影响调用的结果也变得不确定, 为避免引入繁琐的 write-check 编码模式.

(三)可能产生幂等性的场景

通常接口分为两类(查询和修改),对于查询类型的我们认为天然幂等,不管执行多少次只会对数据产生0次影响。而针对修改类型(新增,修改,删除)可能会根据请求数产生n次影响

1. 网络波动,可能会引起重复请求

2. 用户重复操作,用户在有意无意下触发多次请求

3. 自身应用使用了重试机制(rpc重试或业务重试等)

4. 页面重复刷新或提交

5. 用户双击提交按钮

二、项目介绍

项目构建工具maven

项目外成结构图

模块说明

1. idempotent-core: 幂等核心依赖包

 

  • core包主要提供了幂等的拦截实现、计数器的创建销毁、基础配置、以及一些支持业务方个性化自定义处理的接口。
  • 核心类 AbsIdempotentAuthorizationProcessor

        

/**
 * 幂等处理抽象类
 * @author gol
 */
public abstract class AbsIdempotentAuthorizationProcessor implements IdempotentAuthorizationProcessor {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbsIdempotentAuthorizationProcessor.class);

    /**
     * 创建幂等计数器
     *
     * @param idempotentKey  幂等key
     * @param idempotentTime 幂等时间
     * @param timeUnit       时间策略
     * @return boolean
     */
    protected abstract boolean createIdempotentTally(String idempotentKey, Long idempotentTime, TimeUnit timeUnit);

    /**
     * 幂等执行的入口
     *
     * @param idempotentKey  幂等key
     * @param idempotentTime 幂等时间,默认毫秒级别
     * @return boolean
     */
    @Override
    public boolean execute(String idempotentKey, Long idempotentTime) throws IdempotentException {
        LOGGER.info("execute idempotent check, idempotentKey:{},idempotentTime:{}", idempotentKey, idempotentTime);
        return this.execute(idempotentKey, idempotentTime, false);
    }

    /**
     * 幂等执行的入口
     *
     * @param idempotentKey   幂等key
     * @param idempotentTime  幂等时间,默认毫秒级别
     * @param throwsException 是否抛出异常
     * @return boolean
     */
    @Override
    public boolean execute(String idempotentKey, Long idempotentTime, boolean throwsException) throws IdempotentException {
        boolean idempotentTally = createIdempotentTally(idempotentKey, idempotentTime, TimeUnit.MILLISECONDS);
        if (!idempotentTally && throwsException) {
            throw new IdempotentException(IdempotentConstant.IDEMPOTENT_FAIL_MSG);
        }
        return idempotentTally;
    }

    /**
     * @param idempotentKey  幂等key
     * @param idempotentTime 幂等时间
     * @param timeUnit       时间策略,默认毫秒级别
     * @return boolean
     * @throws IdempotentException ex
     */
    @Override
    public boolean execute(String idempotentKey, Long idempotentTime, TimeUnit timeUnit) throws IdempotentException {
        return this.execute(idempotentKey, idempotentTime, timeUnit, false);
    }

    /**
     * @param idempotentKey   幂等key
     * @param idempotentTime  幂等时间
     * @param timeUnit        timeUnit
     * @param throwsException 是否抛出异常
     * @return boolean
     * @throws IdempotentException IdempotentException
     */
    @Override
    public boolean execute(String idempotentKey, Long idempotentTime, TimeUnit timeUnit, boolean throwsException) throws IdempotentException {
        boolean idempotentTally = createIdempotentTally(idempotentKey, idempotentTime, null == timeUnit ? TimeUnit.MILLISECONDS : timeUnit);
        if (!idempotentTally && throwsException) {
            throw new IdempotentException(IdempotentConstant.IDEMPOTENT_FAIL_MSG);
        }
        return idempotentTally;
    }
}

 2、idempotent-reids: 基于redis实现的幂等方案     

  redis包主要实现了幂等的存储、默认bean的配置、以及序列化等

三、使用说明

     1、引入方式:maven引入

<dependency>
            <groupId>org.link.redis</groupId>
            <artifactId>idempotent-redis</artifactId>
            <version>1.0-SNAPSHOT</version>
</dependency>

     2、使用方式:基于方法形式使用拦截        

    @Autowired
    private  IdempotentComponent idempotentComponent;
    
    /**
     * 幂等测试接口
     */
    @GetMapping("insert/{token}")
    public void insert(final HttpServletResponse response,@PathVariable String token) throws IOException {
        PrintWriter writer = response.getWriter();
        String key = token;
        boolean check = idempotentComponent.idempotentCheck(key, 1L,TimeUnit.SECONDS,true);
        if (!check) {
            response.setStatus(500);
            writer.print("insert fail");
            log.info("insert fail...");
        } else {
            response.setStatus(200);
            writer.print("token=" + token + " insert success");
            log.info("token=" + token + " insert success");
        }
        writer.close();
    }

四、幂等详细方法介绍

        

/**
     * 幂等校验
     *
     * @param idempotentKey  幂等key
     * @param idempotentTime 幂等时间,默认毫秒级别
     * @return boolean
     */
    public boolean idempotentCheck(String idempotentKey, Long idempotentTime) {
        return idempotentAuthorizationProcessor.execute(idempotentKey, idempotentTime);
    }

    /**
     * 幂等校验
     *
     * @param idempotentKey   幂等key
     * @param idempotentTime  幂等时间,默认毫秒级别
     * @param throwsException 是否抛出异常
     * @return boolean
     */
    public boolean idempotentCheck(String idempotentKey, Long idempotentTime, boolean throwsException) {
        return idempotentAuthorizationProcessor.execute(idempotentKey, idempotentTime, throwsException);
    }

    /**
     * 幂等校验
     *
     * @param idempotentKey  幂等key
     * @param idempotentTime 幂等时间
     * @param timeUnit       时间策略
     * @return boolean
     */
    public boolean idempotentCheck(String idempotentKey, Long idempotentTime, TimeUnit timeUnit) {
        return idempotentAuthorizationProcessor.execute(idempotentKey, idempotentTime, timeUnit);
    }

    /**
     * 幂等校验
     *
     * @param idempotentKey   幂等key
     * @param idempotentTime  幂等时间
     * @param timeUnit        时间策略
     * @param throwsException 是否抛出异常
     * @return boolean
     */
    public boolean idempotentCheck(String idempotentKey, Long idempotentTime, TimeUnit timeUnit, boolean throwsException) {
        return idempotentAuthorizationProcessor.execute(idempotentKey, idempotentTime, timeUnit, throwsException);
    }

 源码地址

        源码:GitHub - imgolye/idempotent-springboot-star: 幂等组件

        示列:https://github.com/imgolye/idempotent-client-demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值