幂等

Posted nogos

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了幂等相关的知识,希望对你有一定的参考价值。

什么是幂等

  简单说来,如果一个操作多次执行所产生的影响等价于执行一次的影响,我们就称之为幂等。
  实际系统中,幂等是一个极为重要的概念。无论是在大型互联网应用还是企业级架构中,我们都见到REST API被越来越多的采用。而正确实现幂等,往往是API中最难的技术点之一。为什么重要,举一个简单易懂的例子。
  比如,你要处理一次电商网站收款或者付款的交易。当你给微信支付发送这个付款请求后,一个理想的场景是没有任何错误发生,微信支付收到你的付款请求,处理所有转账,然后返回一个HTTP 200消息表示交易完成。
  那如果发出请求后,有个请求超时,你再也没有收到关于这个请求时成功还是失败的回执,又该如何呢?
  这里就有很多种可能情况:
1、这个请求到达微信支付端之前就已经发生超时,微信支付从来没有收到这样的请求。
2、这个请求到达微信支付端,微信支付收到该请求,但是没有处理成功。
3、这个请求到达微信支付端,并且支付交易成功,但是没有回执。
4、这个请求到达微信支付端,并且支付交易成功,同时发回回执,然而因为网络原因回执丢失,客户端超时。

如何实现幂等

  多次执行所产生的影响等价于执行一次的影响,换句话说就是需要找到一种去重机制。通常包含如下几种实现方式:

1、Idempotency Key(幂等令牌)

  客户端和服务器通过什么来识别这实际上是同一个请求,或者同一个请求的多次Retry(重试)。这往往需要双方约定一个协议,例如使用账单号或者交易token(令牌)等唯一标识同一个请求,通常由客户端生成。

2、Uniqueness Guarantee(确保唯一性)

  即服务器端使用什么机制去确保同一个请求一定不会被处理两次。最通常的做法是利用数据库,比如,将幂等令牌所在的Column(列)设置为表的Unique Index(唯一索引)。这样,当你试图存储两个含有相同幂等令牌的请求时,必定有一个会报错。注意,简单的读检查并不一定行,因为并发的读后写会有Race Condition(竞争条件)。

  如果一个系统可以正确的处理和实现上面的两个要素,那么基本就能达到幂等的需求。那么现实系统中常见的问题出在哪里呢?
1、幂等令牌什么时候产生,怎么产生?
  这一点很重要,那上面的例子来说。就算微信支付可以保证每一次请求对应的支付交易只会被处理一次,但是这个请求的多次重复,一定要有一个微信能够唯一识别的标识。假如,客户端对同一笔交易的多次请求,产生的幂等令牌不相同,那么不论你别的地方多么完美,都没有办法保证幂等性。
2、针对Retry的处理
  这大部分是服务端要做的,一个常见的方法是区分正在处理的请求、和处理成功、处理失败的请求。这样,当客户端重试的时候,根据情况或者直接返回,或者再次处理。就好像前面说的微信支付的例子,需要知道每一笔交易的处理情况,才能正确处理在此转账请求时,是不是需要进行任何动作。
3、一个系统中需要多层幂等
  比如,A发送请求给B,B处理的一部分是要发送请求给另一个系统C,C在处理的过程中还可能请求另一个系统D…。D处理完后返回给C,C返回给B,B返回给A。在这个联调中,如果ABCD中任何一个系统并没有实现幂等,也就出现了“幂等漏洞”,那么一个请求还是有可能被多次执行,产生区别于一次执行的影响。

以上是关于幂等的主要内容,如果未能解决你的问题,请参考以下文章

什么是接口的幂等性,如何实现接口幂等性?

Spring Boot 接口幂等插件使用

理解幂等性

幂等性

在微服务架构下,保证接口幂等性

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