浅谈幂等

浅谈幂等

前语

幂等是分布式系统中确保数据一致性和安全性的重要保证之一,尤其是在金融、付出领域,其作为资损防控的硬性指标体现在系统架构规划中。今日咱们就来浅谈一下幂等相关的规划。

幂等的界说

幂等( idempotent、idempotence )的概念来源于数学,并被广泛使用于计算机科学。在数学中,其语意是 f ( x ) = f ( f ( x )),比方求取绝对值,abs ( x ) = abs ( abs ( x )),便是幂等的。

在计算机科学中,幂等即相同的恳求调用一次和调用屡次,服务端处理的的成果相同,而且最多受理一次。

幂等的重要性

咱们就拿付出公司的资金调拨举个例子。一般的,第三方付出公司需求借助清算公司(如网联)供给的付出通道进行备付金账户资金调拨,以确保资金池足够可用。当第三方付出公司建议资金调拨恳求时,假如清算公司的回来成果丢掉,这时,付出公司是否能够重试?假如重试,是否会产生资金的重复调拨?

浅谈幂等

互联网公司的使用间存在物理鸿沟,恳求和响应信息会经过网络进行传递。咱们说远程调用的成果会有三个状况:成功,失败,未知。前两者都是清晰的状况,而未知具有不确定性,一般都是由网络超时、丢包引起的。如上例中,假如呈现了超时,其实有两种方案,咱们能够建立查询补偿机制,来研判是否要从头建议资金调拨。或许,清算公司做好幂等控制,付出公司能够无脑重试,既能够确保资金调拨事务的正常,又能确保不会产生屡次调拨。

在架构规划中,幂等的使用面非常广泛,比方 MQ 躲避重复消费、表单躲避重复提交等。

幂等规划

幂等两大要素

幂等包括两大要素,幂等标记和要害恳求参数。

幂等号:它对应服务端的仅有束缚,在规划上,它一般由上游的幂等单号和来源组成。服务端的接口文档中,需求清晰指出幂等号的信息组成,它的作用是对恳求信息进行身份标识,相同幂等号的恳求将被服务端识别为同一恳求。

要害恳求信息:接收的中心事务信息,常见的如收款账户、打款账户,打款金额、币种、商品数量等等。相同的恳求中,调用方需求确保要害恳求信息不变,一旦信息产生改动,则需求替换幂等号。

幂等原则

调用方有必要确保幂等号的仅有性、不变性

阐明

调用方需求确保幂等号不重复,且对同一事务单据的同一次操作,不管恳求多少次,都要确保幂等号不变。

反例

幂等号重复,原因根本如下

  • sequence cycle 问题,未评价好事务量同 sequence 增长速度,导致幂等号重复。
  • sequence 步长、分段设置问题,导致跨区域/单元/库/表幂等号重复;

幂等号改动,原因根本如下

  • 事务中生成幂等号,并建议远程调用,调用超时本地事务回滚,第2次恳求又会生成新的幂等号。

调用方有必要确保要害事务恳求参数的不变性

阐明

当服务端没有回来成果时,调用方要害事务恳求参数不允许变更。

反例

初度恳求,由于网络反常导致 timeout 调用方没有拿到成果,而服务端受理成功。客户端修改单据金额,恳求信息产生改动,调用方与服务端处理犯错。

浅谈幂等

调用方制止幂等号纯内存拼接,不进行耐久化

阐明

幂等号不耐久化,对于异步回执处理,上下游数据稽核带来困难,所以幂等号耐久化是一个根本要求。

反例

RPC 调用,调用方的幂等号,是内存中依据事务映射拼接得来,不做耐久化。

//内存中拼接幂等号
request.setRequestId(BizTypeEnum.getPrefix(xxDO.getBizType()) + xxxDO.getId()):

调用方幂等号生成事务内制止包括 RPC

反例

transactionTemplate.execute (status ->
  //生成流水号 xxx 
  SerialDO serialDO = buildSerialDO();
  //播入 aaa 表
  serialDAO.insert(serialDO);
  someDAO.update (someDO) ;
  // dubbo 调用 rpc,流水号 xxxId 作为幂等号
  invokeRpc(request);
  return true,
));

正例

  • RPC 放在事务外面
transactionTemplate.execute (status ->
  //生成流水号 xxx 
  SerialDO serialDO = buildSerialDO();
  //播入 aaa 表
  serialDAO.insert(serialDO);
  someDAO.update (someDO) ;
  return true;
));
// dubbo 调用 rpc,流水号 xxxId 作为幂等号
invokeRpc(request);
  • 运用事务同步器:假如事务在外层开启,为了不损坏代码结构,运用事务同步器,事务提交后建议 RPC 调用,调用反常后使用需求做康复。
/**
* 外层已开启事务
*/
public static void execute (){
 //更新单据状况
 Runnable runnable = () -> {
  response = dubboService.call(request);
  };
  register(runnable);
}
​
public static void register (Runnable runnable) {
 if (TransactionSynchronizationManager.isActualTrangactionActive()) {
  TransactionSynchronizationManager.registersynchronization(
   new TransactionSynchronizationAdapter() {
    @Override
    public void afterCommit () {
     runnable.run(); 
     } 
    }
   ); 
  } else {
  LOGGER.debug( "No active transaction.");
  runnable.run();
  }
}
​
  • 事务自研组件:事务中插入本地任务,统一康复执行。

服务端不能单纯依赖查询做幂等

阐明

分布式下并发场景,并不能单纯的依赖查询做到插入 幂等。常见仅有性保证方法:

  • DB 束缚:对插入流水的幂等号建 DB 仅有索引束缚
  • 分布式锁:如 redis、 zookeeper 等。若耐久层在 DB,不推存运用(依赖外部存储做幂等控制,与 DB 的强一致性无法确保),触及资金等强一致性场景不引荐。

反例

RPC 调用超时,本地事务回滚。下次重试,会生成新的幂等号,导致资损。

服务端有必要确保受理成果一致性

阐明

针对相同恳求,不论调用方恳求多少次,服务端仅受理一次,且受理成果相同。

反例

售中退款的场景中,第一次服务端正常受理调用方恳求,但调用方由于超时丢掉响应;当第2次调用方重试,服务端发现退款金额不足,回来受理失败,导致毛病。

//1、根本校验
//2、失望锁内,可退款金额判别;
Assert.isTrue(refundable(xxx), "cannot refund");
​
//3、逻辑处理
try {
  process(xxx);
} catch (Exception e) {
    //幂等判别处理
}

调用方收到服务端幂等成果后,比对要害事务参数

阐明

客户端收到服务端成果后,本着不信任的原则,针对要害事务恳求参数如账户、 金额同服务端受理内容对比。

反例

服务端做幂等判别时,只看幂等号,尽管第2次恳求幂等号不变,但是金额又或许被篡改,假如服务端直接回来成功,将导致资金丢失。

正例

  • 服务端:依据幂等号查询 DB 流水,回来现已受理的要害事务信息。
  • 调用方:对服务方回来的幂等内容做校验,确保与预期一致。

总结

以上规则是借鉴历史项目和互联网经验总结而成,主要侧重于幂等规划的原则,幂等的落地方案有许多,比方幂等表、乐观锁、失望锁等,这儿就不赘述。

引荐阅读

政采云 Flutter 单元测试实践

音视频技能助力政府采购之音视频编码采集(一)

以dubbo源码为例-运用lambda重构面向对象模块

万字长文解读 Linux 内核追踪机制

spring-retry详解

招贤纳士

政采云技能团队(Zero),Base 杭州,一个赋有激情和技能匠心精神的成长型团队。规划 500 人左右,在日常事务开发之外,还分别在云原生、区块链、人工智能、低代码渠道、中间件、大数据、物料系统、工程渠道、性能体验、可视化等领域进行技能探索和实践,推进并落地了一系列的内部技能产品,继续探索技能的新鸿沟。此外,团队还纷纷投身社区建造,目前现已是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等很多优秀开源社区的贡献者。

假如你想改动一向被事折腾,期望开端折腾事;假如你想改动一向被劝诫需求多些主意,却无从破局;假如你想改动你有才能去做成那个成果,却不需求你;假如你想改动你想做成的事需求一个团队去支撑,但没你带人的方位;假如你想改动本来领悟不错,但总是有那一层窗户纸的模糊……假如你信任信任的力量,信任平凡人能成就非凡事,信任能遇到更好的自己。假如你期望参与到随着事务腾飞的进程,亲手推进一个有着深化的事务了解、完善的技能系统、技能发明价值、影响力外溢的技能团队的成长进程,我觉得咱们该聊聊。任何时刻,等着你写点什么,发给 zcy-tc@cai-inc.com

微信大众号

文章同步发布,政采云技能团队大众号,欢迎重视

浅谈幂等