如果保证接口的幂等性

前言

大家好,我是一只笨拙还坚持努力看源码的小蜗牛。今天的主题是接口的幂等性,如果你从没了解过,那么你现在面部表情肯定跟我当初看到这个名词的一样,然后心里大骂一声,什么鬼?那么今天,我来解释下这个鬼玩意到底是什么。

接口的幂等性

幂等性原本是数学上的概念,即公式:f(x) = f(f(x)) 能够成立的数学性质
那么在编程领域,为对一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的
幂等性是分布式系统设计中非常重要的概念,具有这一性质的接口在设计时总是秉持这样的一种理念:调用接口发生异常并且重复尝试时,总是会造成系统无法承受的损失,所以必须阻止这种现象的发生。

为何要保证接口的幂等性

试想一下这样的一种场景:在电商平台上支付后,因为网络原因导致系统提示你支付失败,于是你又重新付款了一次,等完成后发现你的网银上被扣款了两次,这是一种什么样的体验。

造成上述问题的原因可能很多,例如第一次付款的时候实际支付后,后台已经发生了扣款,但是因为网络的原因,导致系统的误判。又比如第一次付款确实失败了,第二次付款重复发送了两次,导致了两次扣款。

幂等性就是解决这类问题的方案之一。在电商,银行,金融公司对数据的准确性和一致性要去很高,所以这一特性具有十分重要的地位。

幂等性的常见思路

1,乐观锁
在数据更新的时候,先去查询数据的版本号,如果版本号一致才允许更新,否则操作无法成功。这是高并发的时候效率高的一种锁机制。
2,建立唯一索引
在表中给一个字段或者时两个字段组合建立唯一索引,当第一次插入数据成功以后,以后重复的请求,插入数据永远无法成功。
3,TOKEN机制
这种机制就比较重要了,适用的范围也比较广,实现的方式也比较多。
核心思路就是,为每一次操作加一个token验证,验证通过则处理,处理完了删除token。当重复请求过来,就无法通过token的验证了。

比如,支付订单之前我先发起一次请求到后台去申请token,然后存放到redis中。然后我真正发起支付请求,我先去验证该请求的token是否存在,如果存在则继续操作。如果不存在,就可以判断是重复请求。

好了,今天的分享就此结束,感谢!

在Spring Cloud项目中,保证接口幂等性是非常重要的,尤其是在微服务架构下。下面将介绍几种常见的策略和技术手段来确保接口幂等性。 ### 1. **使用全局唯一ID(UUID)** 每条请求都应带上一个全球唯一的标识符(UUID),以此作为去重的关键依据。我们可以在过滤器或拦截器处对该UUID进行校验,避免重复处理相同的请求。 #### 实现步骤: - 客户端生成并传递`requestId` - 服务器接收到请求后将其存入Redis或其他缓存工具里 - 当再次接到相同`requestId`时,直接返回之前的响应结果 ```java public class IdempotentFilter extends OncePerRequestFilter { @Autowired private RedisTemplate<String, String> redisTemplate; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 获取 requestId 参数值 String requestId = request.getParameter("idempotencyKey"); if (redisTemplate.opsForValue().get(requestId) != null) { // 已经有该键表示已经执行过了 直接结束掉本次调用 return; } try { // 执行正常链路逻辑... filterChain.doFilter(request, response); // 设置到缓存中防止下次再进入业务层逻辑里面去了 防止并发场景导致的问题 redisTemplate.opsForValue().set(requestId, "executed", Duration.ofMinutes(5)); } catch (Exception e){ throw new RuntimeException(e.getMessage()); } } } ``` ### 2. **乐观锁机制** 对于一些涉及数据变更的操作,我们可以利用数据库表中的版本号字段(`version`)来进行判断。当发生更新操作时,除了指定要修改的数据外还要附加当前记录对应的版本信息。SQL语句会添加额外条件限制只能作用于特定版本的数据行上;如果实际影响行数不符合预期说明其他地方抢先一步进行了改动那么此时应当告知用户尝试刷新页面获取最新的状态后再试一次即可。 ```sql UPDATE orders SET status='PAID', version=version+1 WHERE order_id=? AND version=? ``` **注:** `order_id` 和 `version` 分别对应订单编号及版本计数。 ### 3. **基于消息队列的幂等消费** 考虑到异步任务的存在情况,如RabbitMQ/Kafka这类的消息中间件可能会因为网络抖动等原因造成消费者重复接收同一条消息的情形。因此我们需要在消费方建立一套针对主题/分区偏移量映射关系的记忆库,从而杜绝此类现象的发生几率。 --- 以上就是在Spring Cloud环境下常用的几种保证接口幂等性的做法。当然根据具体的业务需求还可以有更多的解决方案可供选择。总之核心思想就是尽量减少不必要的资源竞争以及引入合适的协调组件共同协作达成目标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值