如何保证接口的幂等性。。。。。

在微服务架构下,我们在完成一个订单流程时经常遇到下面的场景:

  1. 一个订单创建接口,第一次调用超时了,然后调用方重试了一次
  2. 在订单创建时,我们需要去扣减库存,这时接口发生了超时,调用方重试了一次
  3. 当这笔订单开始支付,在支付请求发出之后,在服务端发生了扣钱操作,接口响应超时了,调用方重试了一次
  4. 一个订单状态更新接口,调用方连续发送了两个消息,一个是已创建,一个是已付款。但是你先接收到已付款,然后又接收到了已创建
  5. 在支付完成订单之后,需要发送一条短信,当一台机器接收到短信发送的消息之后,处理较慢。消息中间件又把消息投递给另外一台机器处理

以上问题,就是在单体架构转成微服务架构之后,带来的问题。当然不是说单体架构下没有这些问题,在单体架构下同样要避免重复请求。但是出现的问题要比这少得多。

为了解决以上问题,就需要保证接口的幂等性,接口的幂等性实际上就是接口可重复调用,在调用方多次调用的情况下,接口最终得到的结果是一致的。有些接口可以天然的实现幂等性,比如查询接口,对于查询来说,你查询一次和两次,对于系统来说,没有任何影响,查出的结果也是一样。

除了查询功能具有天然的幂等性之外,增加、更新、删除都要保证幂等性。那么如何来保证幂等性呢?

全局唯一ID

如果使用全局唯一ID,就是根据业务的操作和内容生成一个全局ID,在执行操作前先根据这个全局唯一ID是否存在,来判断这个操作是否已经执行。如果不存在则把全局ID,存储到存储系统中,比如数据库、redis等。如果存在则表示该方法已经执行。

从工程的角度来说,使用全局ID做幂等可以作为一个业务的基础的微服务存在,在很多的微服务中都会用到这样的服务,在每个微服务中都完成这样的功能,会存在工作量重复。另外打造一个高可靠的幂等服务还需要考虑很多问题,比如一台机器虽然把全局ID先写入了存储,但是在写入之后挂了,这就需要引入全局ID的超时机制。

使用全局唯一ID是一个通用方案,可以支持插入、更新、删除业务操作。但是这个方案看起来很美但是实现起来比较麻烦,下面的方案适用于特定的场景,但是实现起来比较简单。

去重表

这种方法适用于在业务中有唯一标的插入场景中,比如在以上的支付场景中,如果一个订单只会支付一次,所以订单ID可以作为唯一标识。这时,我们就可以建一张去重表,并且把唯一标识作为唯一索引,在我们实现时,把创建支付单据和写入去去重表,放在一个事务中,如果重复创建,数据库会抛出唯一约束异常,操作就会回滚。

插入或更新

这种方法插入并且有唯一索引的情况,比如我们要关联商品品类,其中商品的ID和品类的ID可以构成唯一索引,并且在数据表中也增加了唯一索引。这时就可以使用InsertOrUpdate操作。在mysql数据库中如下:


1

2

3

4


insert into goods_category (goods_id,category_id,create_time,update_time)

values(#{goodsId},#{categoryId},now(),now())

on DUPLICATE KEY UPDATE

update_time=now()

多版本控制

这种方法适合在更新的场景中,比如我们要更新商品的名字,这时我们就可以在更新的接口中增加一个版本号,来做幂等


1

boolean updateGoodsName(int id,String newName,int version);

在实现时可以如下


1

update goods set name=#{newName},version=#{version} where id=#{id} andversion<${version}

1. 通过版本号实现 
update table_xxx set name=#name#,version=version+1 where version=#version# 
如下图(来自网上):

2. 通过条件限制 
update table_xxx set avai_amount=avai_amount-#subAmount# where avai_amount-#subAmount# >= 0 
要求:quality-#subQuality# >= ,这个情景适合不用版本号,只更新是做数据安全校验,适合库存模型,扣份额和回滚份额,性能更高

注意:乐观锁的更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,上面两个sql改成下面的两个更好 
update table_xxx set name=#name#,version=version+1 where id=#id# and version=#version# 
update table_xxx set avai_amount=avai_amount-#subAmount# where id=#id# and avai_amount-#subAmount# >= 0

状态机控制

这种方法适合在有状态机流转的情况下,比如就会订单的创建和付款,订单的付款肯定是在之前,这时我们可以通过在设计状态字段时,使用int类型,并且通过值类型的大小来做幂等,比如订单的创建为0,付款成功为100。付款失败为99

在做状态机更新时,我们就这可以这样控制


1

update `order` set status=#{status} where id=#{id} and status<#{status}

如何保证接口的幂等性。。。。。

原文地址:https://www.cnblogs.com/hellohorld/p/11141137.html

时间: 2024-11-05 22:06:05

如何保证接口的幂等性。。。。。的相关文章

接口的幂等性原则

接口调用存在的问题 现如今我们的系统大多拆分为分布式SOA,或者微服务,一套系统中包含了多个子系统服务,而一个子系统服务往往会去调用另一个服务,而服务调用服务无非就是使用RPC通信或者restful,既然是通信,那么就有可能在服务器处理完毕后返回结果的时候挂掉,这个时候用户端发现很久没有反应,那么就会多次点击按钮,这样请求有多次,那么处理数据的结果是否要统一呢?那是肯定的!尤其在支付场景.什么是接口幂等性 接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而

分布式系统中接口的幂等性(转)

业务场景 公司有个借贷的项目,具体业务类似于阿里的蚂蚁借呗,用户在平台上借款,然后规定一个到期时间,在该时间内用户需将借款还清并收取一定的手续费,如果规定时间逾期未还上,则会产生滞纳金. 用户发起借款因此会产生一笔借款订单,用户可通过支付宝或在系统中绑定银行卡到期自动扣款等方式进行还款.还款流程都走支付系统,因此用户还款是否逾期以及逾期天数.逾期费等都通过系统来计算. 但是在做订单系统的时候,遇到这样一个业务场景,由于业务原因允许用户通过线下支付宝还款,即我们提供一个公司官方的支付宝二维码,用户

保证接口幂等性的解决方案(后台)

假如有个服务提供一个接口(服务部署在多个服务机器),接着有个接口是付款接口.用户在前端上操作的时候,一个订单不小心发起了两次支付请求,然后这两个请求分散在了这个服务部署的不同的机器上,结果一个订单扣款扣两次.这样的场景,就是接口没有保证幂等性的结果. 保证幂等性的核心 1.对于每个请求必须有一个唯一的标识. 2.每次处理完请求之后,必须有一个记录标识这个请求处理过了. 3.每次接收请求需要进行判断之前是否处理过的逻辑处理. 常见解决方案 1.业务表内唯一索引 如果要对创建销售出库单的接口保证幂等

解决并发保证数据一致性、幂等性方案

解决高并发.保证数据一致性.幂等性的方案 基本思路:在每次请求服务之前,先必须调用"令牌服务",获得一个唯一的令牌,然后再带上令牌ID这个参数去调用相关的服务.由于这个令牌ID是唯一的,所以,这样可以有效的防止同一个业务多次执行. 具体步骤如下: step1.首先在数据库中创建一个存放令牌相关信息的表open_ticket: step2.定义调用令牌服务的参数:至少包括 操作用户.业务编号.业务场景类型: step3.定义获取"令牌"的服务TicketDTO bui

分布式高并发系统如何保证对外接口的幂等性?

详细请参考知乎上面的回答:http://www.zhihu.com/question/27744795 我觉得回答的比较好的,原文如下: 重复消息是SOA服务实现中非常常见的问题,你永远不要指望调用方每次请求消息不一样,对于读操作,重复消息可能无害,可对于写操作很可能就是灾难.可以通过幂等(Idempotent)模式处理重复的消息,基本处理思路是:1.调用者给消息一个唯一请求ID标识.ID标识一个工作单元,这个工作单元只应执行一次,工作单元ID可以是Schema的一部分,也可以是一个定制的SOA

分布式服务接口的幂等性如何设计

面试官心理分析 从这个问题开始,面试官就已经进入了实际的生产问题的面试了. 一个分布式系统中的某个接口,该如何保证幂等性?这个事儿其实是你做分布式系统的时候必须要考虑的一个生产环境的技术问题.啥意思呢? 你看,假如你有个服务提供一些接口供外部调用,这个服务部署在了 5 台机器上,接着有个接口就是付款接口.然后人家用户在前端上操作的时候,不知道为啥,总之就是一个订单不小心发起了两次支付请求,然后这俩请求分散在了这个服务部署的不同的机器上,好了,结果一个订单扣款扣两次. 或者是订单系统调用支付系统进

接口的幂等性

http://blog.csdn.net/fbysss/article/details/8024748 [原创链接: http://www.smithfox.com/?e=16 转载请保留此声明, 谢谢] 绝大部分网络上对幂等性的解释类似于: "幂等性是指重复使用同样的参数调用同一方法时总能获得同样的结果.比如对同一资源的GET请求访问结果都是一样的." 我认为这种解释是非常错误的, 幂等性强调的是外界通过接口对系统内部的影响, 外界怎么看系统和幂等性没有关系. 就上面这种解释, Sy

分布式事务解决(5):可靠消息的最终一致性方案-消息重复发送问题与业务接口的幂等性设计

一.消息消费流程的异常分析与处理 1.1.消息消费流程的异常点 1.2.消息消费流程的异常处理 方法:对于未确认的消息,采用按规则重新投递的方式进行处理. 问题:消息的重复发送会导致业务处理接口出现重复调用的问题. 未完,待续....

micro-service(3):分布式事务和接口幂等性

分布式服务需要满足CAP原则,Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性),但三者不可得兼:一般都会优先保证可用性和分区容错性,并且保证最终一致性.BASE理论是对CAP原则的补充,Basically Available,Soft state,Eventually Consistent,也就是当CAP三者不能兼得的时候,可以做到最终一致性. 大型应用一般需要做业务分拆以便于提升业务的可维护性和扩展性,但由于业务分布于