vlambda博客
学习文章列表

分布式架构中的幂等性

 

程序猿小白


今天我们学习什么新知识?

攻城狮小明

我们来学一下分布式架构中的幂等性。


  分布式架构中的幂等性

幂等性


幂等性(Idempotence):分布式架构的基石,即同一个操作无论请求多少次,其结果都相同。



在以前的单应用系统中,我们只需要把数据操作放入事务中即可,发生错误立即回滚,但是再响应客户端的时候也有可能出现网络中断或者异常等等。







举个最简单的例子:

*支付

用户购买商品时使用网上支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条。

分布式架构中的幂等性
分布式架构中的幂等性
分布式架构中的幂等性

  分布式架构中的幂等性

攻城狮小明


如何解决上述问题呢,此时就需要用到幂等设计。


幂等设计

       单次支付请求,也就是直接支付了,不需要额外的数据库操作了,这个时候发起异步请求创建一个唯一的ticketId,就是门票,这张门票只能使用一次就作废,具体步骤如下:

1.异步请求获取门票

2.调用支付,传入门票

3.根据门票ID查询此次操作是否存在,如果存在则表示该操作已经执行过,直接返回结果;如果不存在,支付扣款,保存结果

4.返回结果到客户端

如果步骤4通信失败,用户再次发起请求,那么最终结果还是一样的

分布式架构中的幂等性

举例:假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时用类函数的方式记为:

bool withdraw(account_id, amount)

       withdraw的语义是从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。

       我们可以通过一些技巧把withdraw变成幂等的,比如:

int create_ticket()

bool idempotent_withdraw(ticket_id, account_id, amount)

        create_ticket的语义是获取一个服务器端生成的唯一的处理号ticket_id,它将用于标识后续的操作。idempotent_withdraw和withdraw的区别在于关联了一个ticket_id,一个ticket_id表示的操作至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就可以放心地多次调用。

        基于幂等性的解决方案中一个完整的取钱流程被分解成了两个步骤:

1、调用create_ticket()获取ticket_id;

2、调用idempotent_withdraw(ticket_id, account_id, amount)。

        虽然create_ticket不是幂等的,但在这种设计下,它对系统状态的影响可以忽略,加上idempotent_withdraw是幂等的,所以任何一步由于网络等原因失败或超时,客户端都可以重试,直到获得结果。如图所示:

分布式架构中的幂等性

和分布式事务相比,幂等设计的优势在于它的轻量级,容易适应异构环境,以及性能和可用性方面。在某些性能要求比较高的应用,幂等设计往往是唯一的选择。



幂等性是高并发分布式架构、分布式系统数据一致性的底层基本原理。


  分布式架构中的幂等性

程序猿小白


又学到了新的知识,我会继续努力学习的。

攻城狮小明

我们也会持之以恒为大家带来好的知识分享,下节课再见。


 


小白程序猿

你若有干货或程序开发中的趣事,欢迎前来爆料啊~