zoukankan      html  css  js  c++  java
  • 在微服务架构下,保证接口幂等性

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

    ①一个订单创建接口,第一次调用超时了,然后调用方重试了一次。
    ②在订单创建时,我们需要去扣减库存,这时接口发生了超时,然后调用方重试了一次。
    ③当这笔订单开始支付,在支付请求发出之后,在服务端发生了扣钱操作,接口响应超时了,然后调用方重试了一次。

      一个订单状态更新接口,调用方连续发送了两个消息,一个是已创建,一个是已付款。但是你先接收到已付款,然后又接收到了已创建。在支付完成订单之后,需要发送一条短信,当一台机器接收到短信发送的消息之后,处理较慢。消息中间件又把消息投递给另外一台机器处理。以上问题,就是在单体架构转成微服务架构之后,带来的问题。当然不是说单体架构下没有这些问题,虽然在单体架构下同样要避免重复请求,但是单体架构出现问题的概率要比这低得多。

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

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

    全局唯一ID

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

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

    去重表

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

    多版本控制

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

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

      在实现时可以如下:

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

    有限状态机控制

      在日常工作过程中,我们经常会遇到状态的变化场景,例如订单状态发生变化,商品状态的变化。我们称这些状态的变化为有限状态机,英文缩写为FSM( F State Machine)。之所以称其为有限,是因为这些场景中的状态往往是可以枚举出来的、数量有限的,所以称其为有限状态机。

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

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

    状态模式

      类似状态机控制策略,我们也可以使用状态模式进行幂等性处理。例如,如果订单状态不是付款中,就不可以将订单状态改为付款成功状态。

    小结

      以上就是保证接口幂等性的一些方法。大家对于接口幂等性都是怎么看的呢?欢迎在文章下方留言讨论!小编会仔仔细细地阅读每条留言。

    Reference


      读后有收获,小礼物走一走,请作者喝咖啡。

    赞赏支持

  • 相关阅读:
    变量与常量
    .面向过程和面向对象的区别
    .JDK,JRE,JVM三者关系
    DEV C++, 利用链表实现目录内所有文件列表显示
    swith的用法和注意事项?
    Java排序(一)实现类的排序
    C++数据结构——树(基础知识篇)
    杀进程
    监控 monitor java 代码
    putty 直接连 快捷键方式
  • 原文地址:https://www.cnblogs.com/east7/p/14853840.html
Copyright © 2011-2022 走看看