0%

接口的幂等性设计

    在高并发或者是安全要求下,后端接口会有多次执行的结果与一次执行的结果要一致的要求,这种接口就叫幂等性接口,需要用到幂等性的接口比较常见的就是用户下单支付等,防止出现重试时对业务造成巨大灾害的危险。下文为设计方案的各个要点。

前端幂等控制

  1. 按钮只能点击一次,如用户点击提交订单号,按钮变灰或页面显示loding状态。防止用户重复点击。
  2. 重定向机制,当用户提交了表单,跳转到另外一个等待处理的页面,然后后台处理完成后再跳转到成功或者失败的界面。这样避免用户按F5刷新浏览器导致重复提交。

全局唯一ID

    要做到幂等性,就需要借助一个唯一的ID来标志每次交易。唯一ID根据业务情况来定,在执行操作前先根据这个全局唯一ID是否存在,来判断这个操作是否已经执行。如果不存在则把全局ID,存储到存储系统中,比如数据库、redis等。如果存在则表示该方法已经执行。
    从工程的角度来说,使用全局ID做幂等可以作为一个业务的基础的微服务存在,在很多的微服务中都会用到这样的服务,在每个微服务中都完成这样的功能,会存在工作量重复。另外打造一个高可靠的幂等服务还需要考虑很多问题,比如一台机器虽然把全局ID先写入了存储,但是在写入之后挂了,这就需要引入全局ID的超时机制。

状态机制控制

    很多时候业务表是有状态的,比如订单表中有:1-下单、2-已支付、3-完成、4-撤销等状态。如果这些状态的值是有规律的,按照业务节点正好是从小到大,我们就能通过它来保证接口的幂等性。在更新表时判断状态字段是否符合即可,当数据库更新成功时会返回影响的行数,这样就可做后续的成功与否的逻辑处理。
    在作者另一篇文章提到了关于消息队列如何去重的文章里,提到的就是用状态机制来控制的方案,业界通常叫这种方式为重试机制,这里放个图。

分布式锁

    分布式锁的机制跟全局唯一ID是相似的,不过既然是锁,那就说明同时只能有一个线程执行同一种操作,对高并发场景是不太适用的,分布式锁分三种实现方式:数据库唯一索引、redission、zookeeper,感兴趣深入的可自行查找相关资料,这里就不扩展了。

消息队列

    将请求快速的接收下来,放入消息队列中,后续消费者服务可自行用逻辑去重。此方法优点是异步处理、高吞吐,不足是不能及时返回请求结果。