面试必问:接口幂等性
共 2611字,需浏览 6分钟
·
2024-04-17 18:17
一
总体介绍
幂等(Idempotence)是一个计算机领域中的概念,通俗来讲,如果用户对一个操作发起一次或者多次请求,得到的结果都是一样的,那么就认为这样的操作是幂等的。HTTP规范对于幂等的说明如下:
A request method is considered idempotent if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.
幂等性主要是指重复请求的场景,比如:
-
用户多次点击提交按钮 由于网络原因触发了重试机制
页面回退后再次提交
消息重复消费
简单来讲,接口最终都是对于数据的操作,也就是数据库的增删改查(CRUD),我们来分析一下,在发起多次相同的请求时,这些操作的幂等性:
二
幂等性的解决方案
根据业务场景,在数据库表中添加唯一索引,这样的话,如果向数据库中插入已经存在的业务数据,系统就会抛出异常,避免了重复数据的插入。
比如一个订单系统,把订单号作为唯一索引,前端提交订单之前,请求发号器生成一个订单号,然后把订单号加入到请求头中,后端程序保存订单信息到数据库中,如果抛出异常,数据不会重复插入,但可以向用户返回下单成功的提示:
当然,这种方式完全依赖数据库的唯一索引特性,虽然很安全,很好地避免了数据重复问题,但把问题全部抛给了数据库层面,会导致性能问题,同时,即使是数据重复了,也提示下单成功,对于用户不太友好。
下面我们以一个实例来演示一下这种做法,假如订单表中的数据如下:
UPDATE orders SET amount=102,version=version+1 WHERE order_id=1003 AND version=5
在上面的更新语句中,WHERE条件把version=5也加上了,如果这个更新操作有重复请求,那么最终也只有一条sql能够真正更新数据,因为其中一条sql更新成功后,version就等于6了,其他的sql就没有满足条件的数据了。
使用redis+token的机制来保证幂等性是非常常见的一种手段,需要前后端配合一起来实现,前端首先向后端请求一个token,后续的请求中再带上这个token,接下来服务器再判断redis中是否存在这个token,如果存在,则进行后续的业务操作,否则说明此请求为重复请求。
在高并发的场景下,有一个问题需要考虑,是在业务操作前删除token,还是在业务操作结束之后再删除token?
如果是在业务操作前删除token,如果业务操作执行失败了,但还没有向客户端返回处理结果,此时客户端又进行了重试,但此时token已经删除,那么重试的请求就不再进行业务操作了(比如生成订单这样的操作)。
如果先进行业务操作,再删除token呢?也会有问题,比如第一次的业务操作还没有结束,第二次请求又过来了,这时token还存在,所以第二次请求也会继续执行,显然这是不合理的。
一般情况下,可以采用先删除token的方式,因为这种方式的结果是没有进行业务操作,后续再重新获取token进行操作即可,相对而言要更合理一些。
三三
总结
接口幂等性是并发编程中非常重要的概念,也是各个公司面试中常问的一个问题,本文总结了常见的实现幂等性的几种方案,相对来讲,使用redis+token的方式是一种比较常见且有效的方式,可以满足很多场景的需求。
当然,也还有其它的些手段来实现这样的功能,包括创建去重表、状态机等,都是在应用层面或者数据库层面来实现,此处不再展开。
创作不易,烦请点赞分享,感谢!
推荐阅读: