所有涉及数据变更的接口,都一定要做幂等处理吗?

一个状态同步的接口,如 “将审批单状态同步到 OA 系统”,即使重复同步,目标系统可通过 “审批单 ID + 当前状态” 判断是否需要更新,重复调用不会产生异常状态。

前言

大家好,我是田螺

最近面试了一位Java开发候选人,10年的开发经验,居然不知道接口幂等如何设计。。。

我们本文来聊聊,后端设计的一个重要原则:接口幂等性。以及什么样的接口才做幂等处理。

是否所有的接口都必须进行幂等处理呢?是否所有涉及数据变更的接口,都要做幂等处理呢?

显然不是,我们要综合考虑业务场景、数据重要程度、数据修复难易程度等,灵活判断是否需要幂等设计,避免过度设计!

  1. 什么是接口幂等性?
  2. 哪些接口必须做幂等处理
  3. 哪些接口可酌情不做幂等处理
  4. 通用方案:如何设计幂等接口?
  5. 幂等涉及的分布式唯一ID如何生成
  6. 幂等设计的核心原则

1. 什么是接口幂等性?

幂等是一个数学与计算机科学概念。

  • 在数学中,幂等用函数表达式就是:f(x) = f(f(x))。比如求绝对值的函数,就是幂等的,abs(x) = abs(abs(x))
  • 计算机科学中,幂等表示一次和多次请求某一个资源应该具有同样的副作用,或者说,多次请求所产生的影响与一次请求执行的影响效果相同。

比如说,你调用下游接口做转账,然后接口网络超时了(实际下游转账成功了),然后你用原来的流水号发起重试,如果下游接口不做幂等处理,那就会导致重复支付!

2. 哪些接口必须做幂等处理

判断接口是否需要幂等处理,核心标准是 “重复调用是否会造成业务损失或数据异常”。一般资金交易、订单相关等接口,都要实现幂等性,比如:

  • 支付接口:如用户下单支付、退款、转账等接口。若未做幂等,用户重复发起支付请求,可能导致多笔扣款,引发严重的资金纠纷和用户信任危机。
  • 订单创建接口:若用户因网络延迟重复提交订单,未做幂等会生成多个重复订单,不仅增加库存管理、物流配送的复杂度,还可能导致商家错发货物。

3. 哪些接口可酌情不做幂等处理

有些接口,业务场景简单、数据也相对没那么重要,重复调用概率比较小,且重复调用造成的影响也很小,则可考虑不做幂等处理,以降低开发成本和系统开销。

典型场景如内部OA系统的一些审批

内部审批单(如员工报销审批、部门采购审批)通常具备以下特点,使其无需强制幂等:

  • 调用场景封闭:接口仅在企业内部系统使用,调用者是内部员工或指定系统,不存在外部用户因网络问题重复提交的高频场景
  • 按钮置灰:且内部系统通常会有前端按钮置灰、提交后跳转等逻辑,从源头减少重复调用。
  • 重复影响极小:即使因异常导致审批单重复提交,后续业务流程可通过 “人工校验” 或 “状态判断” 修正,或者驳回流程(或者删除申请流程)再重新发起~

当然,并不是说这类型接口一定不做幂等处理,这个是结合你实际业务场景评估的,有些场景,幂等可以简单处理的,比如:

一个状态同步的接口,如 “将审批单状态同步到 OA 系统”,即使重复同步,目标系统可通过 “审批单 ID + 当前状态” 判断是否需要更新,重复调用不会产生异常状态。(这种方案就是状态机幂等处理

4. 通用方案:如何设计幂等接口?

对于重要接口的幂等处理,比如转账接口,跟大家分享一种比较通用的幂等方案哈~~

日常开发中,为了实现交易接口幂等,我是这样实现的:

交易请求过来,我会先根据请求的唯一流水号bizSeq字段,先select一下数据库的流水表

  • 如果数据已经存在,就拦截是重复请求,直接返回成功;
  • 如果数据不存在,就执行insert插入,如果insert成功,则直接返回成功,如果insert产生主键冲突异常,则捕获异常,接着直接返回成功。

流程图如下:

图片

图片

伪代码如下:

/**
 * 幂等处理
 */
Rsp idempotent(Request req){
  Object requestRecord =selectByBizSeq(bizSeq);

if(requestRecord !=null){
    //拦截是重复请求
     log.info("重复请求,直接返回成功,流水号:{}",bizSeq);
     return rsp;
  }

  try{
    insert(req);
  }catch(DuplicateKeyException e){
    //拦截是重复请求,直接返回成功
    log.info("主键冲突,是重复请求,直接返回成功,流水号:{}",bizSeq);
    return rsp;
  }

  //正常处理请求
  dealRequest(req);

return rsp;
}

为什么前面已经select查询了,还需要try...catch...捕获重复异常呢?

是因为高并发场景下,两个请求去select的时候,可能都没查到,然后都走到insert的地方啦。

当然,一般都是用唯一索引代替数据库主键的哈,主要都是全局唯一的ID即可。我们之前的转账流水,幂等就是基于业务流水号作为唯一索引~~

5. 幂等涉及的分布式唯一ID如何生成

我们处理幂等的时候,就需要分布式的全局唯一ID,我们该如何去生成呢?你可以回想下,数据库主键Id怎么生成的呢?

是的,我们可以使用UUID,但是UUID的缺点比较明显,它字符串占用的空间比较大,生成的ID过于随机,可读性差,而且没有递增。

我们还可以使用雪花算法(Snowflake) 生成唯一性ID。

雪花算法是一种生成分布式全局唯一ID的算法,生成的ID称为Snowflake IDs。这种算法由Twitter创建,并用于推文的ID。

一个Snowflake ID有64位。

  • 第1位:Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。
  • 接下来前41位是时间戳,表示了自选定的时期以来的毫秒数。
  • 接下来的10位代表计算机ID,防止冲突。
  • 其余12位代表每台机器上生成ID的序列号,这允许在同一毫秒内创建多个Snowflake ID。

雪花算法

雪花算法

当然,全局唯一性的ID,还可以使用百度的Uidgenerator,或者美团的Leaf

6. 幂等设计的核心原则

所以,并不是所有的接口都要做幂等处理。本质是 “业务影响” 与 “成本开销” 的权衡。

  • 如果是核心交易、资金相关接口,必须实现幂等,而且最好是基于流水表这种实现,用流水表去跟踪数据、数据状态的流转变化。
  • 对于内部系统的一些简单接口,如审批单,幂等则可以简单处理,或者综合评估可能影响后,不做幂等处理。在 “风险控制” 与 “成本” 之间找到平衡。

我还是想强调一句:幂等设计的最终目标不是 “所有接口都实现幂等”,而是 “让关键接口安全,让简单接口高效”,以合理的设计保障系统稳定,同时避免不必要的开销。

AI大模型学习福利

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。


因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

四、AI大模型商业化落地方案

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值