美文网首页
聊聊幂等

聊聊幂等

作者: VitoPJ | 来源:发表于2017-06-12 21:44 被阅读0次

    什么是幂等(idempotency)?简单一点说,一个操作如果具有任意多次执行所产生的影响与一次执行产生的影响相同,就是幂等。

    这样来说,似乎也很容易理解。但是要知道,这样的定义,其实是一个语义范畴内对行为结果的定义。如果用语法和规则去确保行为能达到这个结果,往往需要很谨慎的设计与实现。在系统中,幂等是一个很重要的概念。无论是在大型的互联网系统还是企业级应用,REST API都被广泛使用。而正确的使用幂等,是API技术中极其重要的一个技术点。

    为什么说非常重要?日常生活中,支付是最常见的交易场景。比如我们在给支付宝发送一笔付款请求时,正常情况下,用户扣款成功,支付宝返回支付成功的信息。但是如果发生异常怎么办?比如客户端发出请求后,请求超时,你没有收到下游系统的处理结果,那到底是成功还是失败,或者其它情况。

    请求超时的情况也分很多种:

    1、这个请求到达支付宝前端之前就发生了超时,也就是支付宝根本就不知道有这笔订单的存在,也就是通常说的漏单。

    2、支付宝已经收到了这个请求,但是支付失败,这时发生超时异常,支付宝处理失败。

    3、支付宝收到了这个请求,并且支付也成功,但这时候还是发生了超时,支付宝处理成功,但时没有回执。

    4、支付宝收到了这个请求,支付也成功,并且发送了回执,但因为网络但原因客户端没有收到,客户端超时,所以并不知道处理结果。

    遇到这种情况怎么办?常见但做法是重试机制,重试机制有几种方案,这里不展开。但是有一个存在的问题,请求超时是上面的那一种,会不会造成重复交易的问题?这就涉及到幂等性问题。

    那么幂等又该如何实现呢?多次执行所产生的影响和一次执行产生的影响相同。简而言之,我们需要一个去重的机制,这往往有很多实现方法,但有两个很关键的因素:

    1、幂等令牌。也就是说客户端和服务端通过什么来识别是同一个请求,或者是一个请求尝试多次。这一般需要客户端和服务端协议,通常由客户端来产生令牌。

    2、确保唯一性。服务端通过什么来确认是同一个请求,也就是说怎么确认请求的唯一性,这通常使用数据库来实现。把幂等令牌作为数据库列的唯一索引。但当有两个同样的幂等令牌到达时,必然有一个会失败。注意一点,简单的读检查并不一定行,因为读与读之间存在竞争条件,因此有可能出错。

    如果一个系统能正确的处理上面两个要素,那基本上就能达到幂等等要求。那么现实系统中,常见等问题都出现在哪里呢?

    1、幂等令牌什么时候产生,怎么产生?这一点很重要。还是拿上面等例子来说,支付宝能确定对每一笔支付请求只执行一次,那它必然有一个唯一标识来区分。假如客户端对同一笔对多次请求,每次请求的幂等令牌都不一样,那支付宝也确认不了这是同一笔交易。

    2、令牌有没有可能被误删的可能。这是上面的一种特殊情况。幂等令牌是由客户端生成的,那么如果客户端在使用完令牌后,不小心因为DB rollback等原因被删除啦。这时客户端就不知道之前已经发送过一次交易。这时候就有可能产生一笔新的交易,并产生一笔新的订单,服务端对此时毫无感知。所以这个必须客户端来保证。

    3、各种竞争条件。上面说的用DB读来确保唯一性经常因为竞争不工作。其实一个实现幂等等系统中,各个环节都需要配合实现,都需要考虑竞争条件。

    4、对服务对重试处理,一般都是服务端实现的。一个常见的做法是要区分正在处理中,处理成功,处理失败。这样当客户端重新请求时,根据具体情况是直接返回还是再次处理。

    5、一个系统中有多个幂等。一个是说服务端不是由一个系统实现的,A系统发给B系统,B系统再发给C系统,C处理完了可能还需要发给D系统,之后再D返回C,C返回B,B再返回A等等各种情况。那么在整个链路中,如果A、B、C、D中有一个系统没有正确的实现幂等,也还是会出现幂等漏洞。

    相关文章

      网友评论

          本文标题:聊聊幂等

          本文链接:https://www.haomeiwen.com/subject/tcnlqxtx.html