如何保证接口的幂等性? 今天我们来聊聊关于接口的幂等性问题。 什么是幂等性 所谓幂等,就是任意多次执行所产生的影响均与一次执行的影响相同。 在 restful 规范中,常见的请求方式和接口幂等性关系如下: 请求方式 操作 是否幂等 GET 查询数据 是 POST 新增数据 否 PUT 更新数据 直接更新为某个值,满足幂等,如:set a = 1;累加操作的更新,不满足,如:set a = a+1 DELETE 删除数据 根据唯一条件删除,满足幂等;否则,不满足,幂等,比如:根据某一条件删除一批数据后,又新增了一条满足该条件的数据,又执行了一次删除,那么就会删除掉新增的这条数据 为什么会产生接口幂等性问题 在计算机应用中,可能遇到网络抖动,临时故障,或者服务调用失败,尤其是分布式系统中,接口调用失败更为常见。为了保证服务的完整性,我们可能会发起接口的重试调用,如果接口不处理幂等,可能对系统造成很大的影响,因此接口的幂等设计尤其更为重要。 对于业务中需要考虑幂等性的地方一般都是接口的重复请求,重复请求是指同一个请求因为某些原因被多次提交。导致这种情况的发生有以下几种常见的场景: 前端重复提交:用户在提交表单的时候,可能会因网络波动没有及时做出提交成功响应,致使用户认为没有成功提交,然后一直点提交按钮,这时就会发生重复提交表单请求。 接口超时重试:第三方调用接口时候,为了超时等异常情况造成的请求失败,都会添加重试机制,导致一个请求提交多次。 消息重复消费:当使用 MQ 消息中间件时候,如果发生消息中间件出现错误未及时提交消费信息,导致发生重复消费。 幂等性解决方案 那我们应该能怎样保证接口的幂等性呢? 可以思考一下,第一种场景下,既然是用户重复提交导致的,那我们可以想办法让用户没办法重复提交。 方案一:前端控制 在前端做拦截,比如按钮一次之后就置灰或者隐藏。但是往往前端并不可靠,还是得后端处理才更放心。 方案二:Token机制 用户进入表单页面首先调用后台接口 token 并存入 redis,当用户提交表单时将 token 也作为入参,后端先删除 redis 中的 token,删除成功则保存表单数据,失败则提示用户重复提交。
这里为什么不先判断 redis 是否存在这个 token 再删除,是因为要保证操作的原子性,极端情况下,第一个请求查询到 redis 中存在这个 token,还没来得及删除,第二个请求进来,也查询到 redis 中存在这个 token,那么还是会造成重复提交的问题。 token 机制需要先请求 token 的接口,在有些情况下很明显并不合适。我们大部分请求都是要落到数据库的,所以我们可以从数据库着手。 方案三、唯一索引 这种方案就比较好理解了,使用唯一索引可以避免脏数据的添加,当插入重复数据时数据库会抛异常,保证了数据的唯一性。唯一索引可以支持插入、更新、删除业务操作。 方案四、悲观锁 这里所说的悲观锁是基于数据库层面的,在数据时进行加锁,当同时有多个重复请求时,其他请求都无法进行操作。悲观锁只适用于更新操作。 注意:id 字段一定要是主键或者唯一索引,不然会锁住整张表,这是会死人的。悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用。 在请求量比较大的情况下,使用悲观锁明显不合适,这时候就到乐观锁上场了。 方案五、乐观锁 可以通过版本号实现,为表增加一个 version 字段,当数据需要更新时,先去数据库里此时的version版本号。 更新数据时首先要对比版本号,如果不相等说明已经有其他的请求去更新数据了,提示更新失败。 还有一种是通过状态机实现的,其实也是乐观锁的原理。这种方法适合在有状态流转的情况下,比如订单的创建和付款,订单的创建肯定是在付款之前,这时我们可以通过在设计状态字段时,使用 int 类型,并且通过值类型的大小来实现幂等性。 同样,乐观锁也只适用于更新操作。 方案六、分布式锁 有时候我们的业务不仅仅是操作数据库,也可能是发送短信、消息等等,那数据库层面的锁就不适合了。这种情况下就要考虑代码层面的锁了,而 java 的自带的锁在分布式集群部署的场景下并不适用,那么就可以采用分布式锁来实现(Redis 或 Zookeeper)。 拿 Redis 分布式锁举例,比如一个订单发起支付请求,支付系统会去 Redis 缓存中查询是否存在该订单号的 Key,如果不存在,则以 Key 为订单号向 Redis 插入。查询订单是否已经支付,如果没有则进行支付,支付完成后删除该订单号的Key。通过 Redis 做到了分布式锁,只有这次订单支付请求完成,下次请求才能进来。当然这里需要设置一个Key 的过期时间,在发生异常的时候还要注意删除 Redis 的 Key。 总结 接口的幂等性是一个很常见的问题,需要根据具体业务场景的不同,选择合适的解决方案。 END 往期推荐 你必须了解的分布式事务解决方案 就这?分布式 ID 发号器实战 略懂设计模式之工厂模式 就这?Spring 事务失效场景及解决方案 就这?一篇文章让你读懂 Spring 事务
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/31944.html