如何保证接口的幂等性--在企业中的实操

本文详细探讨了编程中的幂等性概念及其重要性,特别是在转账和下单等关键业务中的应用。介绍了通过数据库唯一索引和缓存机制来确保幂等性的方法,并深入分析了在业务代码异常、业务系统宕机以及幂等框架异常三种情况下,如何设计和处理幂等性以避免错误。最后,提出了幂等服务框架的一般处理流程,强调了在企业中构建幂等服务的重要性。
摘要由CSDN通过智能技术生成

一.幂等性简介

       对于编程人员来说,就是同一个请求对于某个接口的多次调用和一次调用产生结果一致,就是幂等.
      比如有个转账接口,你想调用给某个人转钱,当第一次调用后没反应,又重复调用了几次, 那如果这个接口执行了正确的操作,只转了一次钱,那么这个接口就是幂等的.

       保证幂等性对于一个接口来说是非常重要的,因为在网络环境中,尤其是在分布式环境中,因前端操作抖动、网络故障、消息重复、响应速度慢等等场景,经常会进行接口的重复调用,重试.如果不保证幂等,造成的影响是很大很大的(比如说转账,下单).

二.幂等性常见的解决方法

       首先要明白有一些接口是天然支持幂等的,如Get请求.
       其次,对于客户端交互的接口,可以在前端拦截一部分,例如防止表单重复提交,按钮置灰,隐藏,不可点击等方式。但是前端进行拦截显然是针对普通用户,懂点技术的都可以模拟请求调用接口,所以后端幂等性很重要。
       这里着重介绍保证后端幂等性的方法.

1.数据库角度

唯一性索引:
       这种只试用于数据新增,针对不同业务,设置相应的唯一性索引,保证不进行重复新增.
比如一个订单表,可以将订单号作为唯一性索引,同一个请求生成的订单号是相同的,也就可以保证幂等.

       此外,在网上看到很多说可以依靠乐观锁,悲观锁,分布式锁保证幂等,对于此,我只想说mmp,不论什么锁,都只是将并发串行化的一种方式,可以解决并发问题,但是单靠这些锁是保证不了幂等的,希望小伙伴在看到后多一些自己的思考.不要被误导.

2.缓存角度

       将每一个业务操作赋予其唯一性,通常就是根据业务属性,内容生成一个全局的唯一性ID
在处理相关业务操作时,先判断这个唯一性ID是否在缓存中,在的话直接返回,否则将这个ID放到缓存中,然后处理业务逻辑.

三.在企业中实际解决方法举例.

实际解决方法以及具体情况分析

       在实际工作中,解决幂等性最常见的方式就是从缓存角度去解决,一般就是redis.整个流程还是挺简单的,就是生成唯一性id(这里就叫幂等号),判断在不在缓存中,在的话直接返回,否则将幂等号放到缓存中,处理业务逻辑.难点在于如何应对异常情况.

       请求的调用过程,一般分为三个阶段,第一阶段是请求发出到业务方接收到请求的过程,第二阶段是业务方处理具体逻辑的过程,第三阶段是将处理结果返回请求方的过程.

       当第一个阶段出现异常,这个时候业务方还没有接受到请求,出现问题本就应该进行重试,符合我们的预期;当第三阶段出现异常,我们已经成功处理请求,但是没有正常返回结果,此时幂等号已经在缓存中,即使重试,也不会进行重复处理,也符合预期;但是当第二阶段出现异常,处理起来就复杂多了,接下来我们就看下应该如何应对这一阶段的各种异常,我分了三类异常来讲解,

  1. 业务代码异常
           当业务代码在执行过程中抛出异常的时候,我们是否应该认定为业务处理失败,然后将已经记录的幂等号删除,允许重新执行业务逻辑呢?
           对于这个问题,我们要分业务异常和系统异常来区分对待。那什么是业务异常?什么是系统异常呢?我举个例子解释一下。比如,A 用户发送消息给 B 用户,但是查询 B 用户不存在,抛出 UserNotExisting 异常,我们把这种业务上不符合预期叫做业务异常。因为数据库挂掉了,业务代码访问数据库时,就会报告数据库异常,我们把这种非业务层面的、系统级的异常,叫做系统异常。
           遇到业务异常(比如 UserNotExisting 异常),我们不删除已经记录的幂等号,不允许重新执行同样的业务逻辑,因为再次重新执行也是徒劳的,还是会报告异常。相反,遇到系统异常(比如数据库访问异常),我们将已经记录的幂等号删除,允许重新执行这段业务逻辑。因为在系统级问题修复之后(比如数据库恢复了),重新执行之前失败的业务逻辑,就有可能会成功。
           实际上,为了让幂等框架尽可能的灵活,低侵入业务逻辑,发生异常(不管是业务异常还是系统异常),是否允许再重试执行业务逻辑,交给开发这块业务的工程师来决定是最合适的了,毕竟他最清楚针对每个异常该如何处理。而幂等框架本身不参与这个决定,它只需要提供删除幂等号的接口,由业务工程师来决定遇到异常的时候,是否需要调用这个删除接口,删除已经记录的幂等号。

  2. 业务系统宕机
           刚刚分析的是代码异常,我们再来看下,如果在业务处理的过程中,业务系统或者说某个实例宕机了(你可以简单理解为部署了业务系统的机器宕机了),幂等框架是否还能正确工作呢?
           如果幂等号已经记录下了,但是因为机器宕机,业务还没来得及执行,按照刚刚的幂等框架的处理流程,即便机器重启,业务也不会再被触发执行了,这个时候该怎么办呢?除此之外,如果记录幂等号成功了,但是在捕获到系统异常之后,要删除幂等号之前,机器宕机了,这个时候又该怎么办?
           这个时候有一个比较好的处理方式就是在我们接收到请求,将幂等号放到缓存中时,可以将过期时间设置的比较短,正常够我们处理业务逻辑的时间就好,当我们成功处理后,再将这个过期时间进行延长,这样假入我们成功保存幂等号之后系统宕机了,几秒钟之后,缓存中的幂等号就会被自动删除,这时候再进行重试,其他实例就可以进行正常处理.

  3. 幂等框架异常
           当执行幂等逻辑时出现异常,比如说Redis 访问超时或者访问失败,或者当我们保存了幂等号之后,redis直接挂了,我们又该怎样处理呢?
           对于幂等来说,它应对的是超时重试等特殊场景,如果本不应该重新执行的业务逻辑,因为幂等功能的暂时失效,被重复执行了,就会导致业务出错(比如,多次执行转账,钱多转了)。对于这种情况,绝大部分业务场景都是无法接受的。所以,在幂等逻辑执行异常时,我们选择让接口请求也失败,相应的业务逻辑就不会被重复执行了。毕竟接口请求失败(比如转钱没转成功),比业务执行出错(比如多转了钱),修复的成本要低很多。

流程总结以及思想升华

       在上面我们介绍了处理幂等性可能出现的各种问题以及对应的处理措施,还有需要注意的是,在一个企业中,有很多很多的接口都需要保证幂等性,那么这个幂等逻辑其实是一样的,所以在企业中,通常会将这个幂等逻辑单独封装成一个服务,一个框架,由业务服务直接调用即可.

这里结合上面所说的各种情况,再总结一下这个幂等服务框架的一般处理流程:

  1. 业务方在业务操作之前,生成一个能够唯一标识该操作的内容字段,传入幂等框架中;幂等框架根据传入的字段,用MD5生成全局唯一性ID;
  2. 然后将全局ID作为key,当前时间戳+传入的内容字段作为value放入redis进行setNx,这个过期时间会比较短,然后将结果返回给业务方;
  3. 业务方根据返回结果确定能否开始进行业务操作;若能,开始进行操作;若不能,则直接结束当前操作;
  4. 业务方将处理后的结果传入幂等框架,若处理失败,直接将对应的全局ID删除,若处理成功,则将该全局ID的过期时间改为较长时间;
  5. 最后幂等框架返回最终结果给业务方.

======================================================================================================
在这里插入图片描述

包含以下所有分类中的各种经典书籍呦.你想要的这里都有
在这里插入图片描述
今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员bling

义父,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值