对于编程人员来说,就是同一个请求对于某个接口的多次调用和一次调用产生结果一致,就是幂等.
比如有个转账接口,你想调用给某个人转钱,当第一次调用后没反应,又重复调用了几次, 那如果这个接口执行了正确的操作,只转了一次钱,那么这个接口就是幂等的.
保证幂等性对于一个接口来说是非常重要的,因为在网络环境中,尤其是在分布式环境中,因前端操作抖动、网络故障、消息重复、响应速度慢等等场景,经常会进行接口的重复调用,重试.如果不保证幂等,造成的影响是很大很大的(比如说转账,下单).
首先要明白有一些接口是天然支持幂等的,如Get请求.
其次,对于客户端交互的接口,可以在前端拦截一部分,例如防止表单重复提交,按钮置灰,隐藏,不可点击等方式。但是前端进行拦截显然是针对普通用户,懂点技术的都可以模拟请求调用接口,所以后端幂等性很重要。
这里着重介绍保证后端幂等性的方法.
唯一性索引:
这种只试用于数据新增,针对不同业务,设置相应的唯一性索引,保证不进行重复新增.
比如一个订单表,可以将订单号作为唯一性索引,同一个请求生成的订单号是相同的,也就可以保证幂等.
此外,在网上看到很多说可以依靠乐观锁,悲观锁,分布式锁保证幂等,对于此,我只想说mmp,不论什么锁,都只是将并发串行化的一种方式,可以解决并发问题,但是单靠这些锁是保证不了幂等的,希望小伙伴在看到后多一些自己的思考.不要被误导.
将每一个业务操作赋予其唯一性,通常就是根据业务属性,内容生成一个全局的唯一性ID
在处理相关业务操作时,先判断这个唯一性ID是否在缓存中,在的话直接返回,否则将这个ID放到缓存中,然后处理业务逻辑.
在实际工作中,解决幂等性最常见的方式就是从缓存角度去解决,一般就是redis.整个流程还是挺简单的,就是生成唯一性id(这里就叫幂等号),判断在不在缓存中,在的话直接返回,否则将幂等号放到缓存中,处理业务逻辑.难点在于如何应对异常情况.
请求的调用过程,一般分为三个阶段,第一阶段是请求发出到业务方接收到请求的过程,第二阶段是业务方处理具体逻辑的过程,第三阶段是将处理结果返回请求方的过程.
当第一个阶段出现异常,这个时候业务方还没有接受到请求,出现问题本就应该进行重试,符合我们的预期;当第三阶段出现异常,我们已经成功处理请求,但是没有正常返回结果,此时幂等号已经在缓存中,即使重试,也不会进行重复处理,也符合预期;但是当第二阶段出现异常,处理起来就复杂多了,接下来我们就看下应该如何应对这一阶段的各种异常,我分了三类异常来讲解,
业务代码异常
当业务代码在执行过程中抛出异常的时候,我们是否应该认定为业务处理失败,然后将已经记录的幂等号删除,允许重新执行业务逻辑呢?
对于这个问题,我们要分业务异常和系统异常来区分对待。那什么是业务异常?什么是系统异常呢?我举个例子解释一下。比如,A 用户发送消息给 B 用户,但是查询 B 用户不存在,抛出 UserNotExisting 异常,我们把这种业务上不符合预期叫做业务异常。因为数据库挂掉了,业务代码访问数据库时,就会报告数据库异常,我们把这种非业务层面的、系统级的异常,叫做系统异常。
遇到业务异常(比如 UserNotExisting 异常),我们不删除已经记录的幂等号,不允许重新执行同样的业务逻辑,因为再次重新执行也是徒劳的,还是会报告异常。相反,遇到系统异常(比如数据库访问异常),我们将已经记录的幂等号删除,允许重新执行这段业务逻辑。因为在系统级问题修复之后(比如数据库恢复了),重新执行之前失败的业务逻辑,就有可能会成功。
实际上,为了让幂等框架尽可能的灵活,低侵入业务逻辑,发生异常(不管是业务异常还是系统异常),是否允许再重试执行业务逻辑,交给开发这块业务的工程师来决定是最合适的了,毕竟他最清楚针对每个异常该如何处理。而幂等框架本身不参与这个决定,它只需要提供删除幂等号的接口,由业务工程师来决定遇到异常的时候,是否需要调用这个删除接口,删除已经记录的幂等号。
业务系统宕机
刚刚分析的是代码异常,我们再来看下,如果在业务处理的过程中,业务系统或者说某个实例宕机了(你可以简单理解为部署了业务系统的机器宕机了),幂等框架是否还能正确工作呢?
如果幂等号已经记录下了,但是因为机器宕机,业务还没来得及执行,按照刚刚的幂等框架的处理流程,即便机器重启,业务也不会再被触发执行了,这个时候该怎么办呢?除此之外,如果记录幂等号成功了,但是在捕获到系统异常之后,要删除幂等号之前,机器宕机了,这个时候又该怎么办?
这个时候有一个比较好的处理方式就是在我们接收到请求,将幂等号放到缓存中时,可以将过期时间设置的比较短,正常够我们处理业务逻辑的时间就好,当我们成功处理后,再将这个过期时间进行延长,这样假入我们成功保存幂等号之后系统宕机了,几秒钟之后,缓存中的幂等号就会被自动删除,这时候再进行重试,其他实例就可以进行正常处理.
幂等框架异常
当执行幂等逻辑时出现异常,比如说Redis 访问超时或者访问失败,或者当我们保存了幂等号之后,redis直接挂了,我们又该怎样处理呢?
对于幂等来说,它应对的是超时重试等特殊场景,如果本不应该重新执行的业务逻辑,因为幂等功能的暂时失效,被重复执行了,就会导致业务出错(比如,多次执行转账,钱多转了)。对于这种情况,绝大部分业务场景都是无法接受的。所以,在幂等逻辑执行异常时,我们选择让接口请求也失败,相应的业务逻辑就不会被重复执行了。毕竟接口请求失败(比如转钱没转成功),比业务执行出错(比如多转了钱),修复的成本要低很多。
在上面我们介绍了处理幂等性可能出现的各种问题以及对应的处理措施,还有需要注意的是,在一个企业中,有很多很多的接口都需要保证幂等性,那么这个幂等逻辑其实是一样的,所以在企业中,通常会将这个幂等逻辑单独封装成一个服务,一个框架,由业务服务直接调用即可.
这里结合上面所说的各种情况,再总结一下这个幂等服务框架的一般处理流程:
======================================================================================================

包含以下所有分类中的各种经典书籍呦.你想要的这里都有

今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
