首页 > 编程知识 正文

如何保证微服务接口的幂等性,update幂等性

时间:2023-05-05 22:12:26 阅读:46130 作者:2865

接口调用问题目前,我们的系统大多分为分布式SOA或微服务。 一个系统包含多个子系统服务,一个子系统服务往往调用另一个服务。 另一方面,既然服务调用服务仅使用RPC通信或rest风格的通信,则当服务器处理完成并返回结果时可能挂起。 此时,如果发现客户端长时间没有反应,可以多次点击按钮,这样的要求有好几次,这一点是肯定的! 特别是在支付场景中。

接口幂等性接口幂等性是指用户对同一操作发起的一次请求或多次请求的结果一致,不会发生多次点击带来的副作用。 举个最简单的例子,那就是支付。 用户购买商品后付款,成功扣款。 但是,结果回来的时候,网络异常。 这个时候,钱已经被提取了。 用户再次单击按钮。 此时,将进行第二次扣款,并返回结果。 用户查了余额后回来,找到了很多扣款。 流水记录也变成了两个。 这不保证接口的幂等性。

在什么情况下需要保证接口的幂等性,在追加删除重新考虑的4个操作中,应该特别注意的是追加或修正

查询操作

查询结果保持不变。 一次查询和多次查询,如果数据不变,则查询结果相同。 select是天然幂等操作。

删除操作

删除一次和多次都是删除数据。 (请注意结果可能不同。 已删除的数据不存在。 返回0。 删除的数据有多个,结果有多个。 在不考虑返回结果的情况下,删除操作也具有乘方等属性。

更新操作

修改在大多数场景中的结果相同,但增量修改需要确保幂等性,如下例所示:

将表中id为XXX的记录的a场的值设定为1的操作,无论执行多少次都是幂等,将表中的id为XXX的记录的a场的值增加1的操作不是幂等

新增操作

增加重复提交的场景时,会发生上述支付问题等乘方等问题

那么,如何设计接口才能进行幂等呢?常见的两种实现方案

1、通过代码逻辑判断实现

2、使用token机制实现。 以支付系统为例,分别说明并实现接口的幂等性

A、通过代码逻辑判断实现接口幂等性,只能针对一些满足判断的逻辑实现,具有一定局限性

用户购买商品的订单系统和支付系统订单系统负责记录用户的购买记录已经订购的分销状态,支付系统用于支付,提供以下接口,订单系统和支付系统

boolean pay (int accountid, BigDecimal amount) // 用于付款,扣除用户的

在这种情况下,虽然支付系统已经被提取,但由于订单系统是网络的,所以无法得到正确的结果。 因此,订单系统需要重试。 从上图可以看出,支付系统没有实现接口的幂等性,订单系统的第一次调用和第二次调用,用户分别被扣两次钱,不符合幂等性原则(同一订单,无论调用多少次) 如果需要支持幂等性,则必须将支付接口更改为以下接口:

boolean pay (int orderId, int accountId, BigDecimal amount)

使用orderId确定订单的唯一性。 如果支付系统检测到订单已支付,则在第二次呼叫中不会被提取,而是直接返回结果。

不同的业务需要不同的接口幂等性,尤其是分布式系统,由于网络原因不能得到确定的结果,往往需要支持接口幂等性。

随着分布式系统和微服务的普及,由于网络原因,呼叫系统得不到适当的结果而进行重试,需要呼叫系统具有幂等性。 举例来说,在上述支付系统中,保证同一订单的支付幂等性,且一旦确定订单的支付状态,后续操作将返回相同结果,且对用户的扣款也仅为一次。 这种接口幂等性简化了数据级别上的操作:

udateuseramountsetamount=amount -‘value’,pay status=‘paid’where orderid=‘orderid’andpaystatus=‘un pay’其中的ve

在上述订单系统中,订单有自己的“状态”,订单的状态有一定的流程。 订单首先有提交(0)、支付中(1)、支付成功(2)、支付失败(3),简化后的流程路径如下。

orderStatus=1时,其前置状态只有0。 也就是说,必须从0-1开始对orderStatus求幂

updateordersetorderstatus=1where orderid=‘orderid’and order status=0

当 orderStatus 处于0,1两种状态时,对订单执行 0->1 的状态流转操作应该是具有幂等性的。这时候需要在执行 update 操作之前检测 orderStatus 是否已经 =1,如果已经 =1 则直接返回 true 即可。

但是如果此时 orderStatus = 2,再进行订单状态 0->1 时操作就无法成功,但是幂等性是针对同一个请求的,也就是针对同一个 requestid 保持幂等。

这时候再执行

update Order set orderStatus = 1 where OrderId = ‘orderid’ and orderStatus = 0

接口会返回失败,系统没有产生修改,如果再发一次,requestid是相同的,对系统同样没有产生修改。

B、使用 token 机制实现接口幂等性,通用性强的实现方法

 token 机制实现步骤

 1、生成全局唯一的token,token放到redis或jvm内存,token会在页面跳转时获取。存放到pageScope中,支付请求提交先获取token

 2、提交后后台校验token,执行提交逻辑,提交成功同时删除token,生成新的token更新redis,这样当第一次提交后token更新了,页面再次提交携带的token是已删除的token后台验证会失败不让提交

 token 特点  

要申请,一次有效性,可以限流

注意: redis要用删除操作来判断token,删除成功代表token校验通过,如果用select + delete来校验token,存在并发问题,不建议使用​​​​​​​

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。