资讯专栏INFORMATION COLUMN

幂等的实现方案

NikoManiac / 3301人阅读

摘要:幂等实现方案幂等性不能脱离业务来讨论。在不同的需求场景下,实现幂等的思路和方案也会不同,一般有如下通用方案多版本并发控制这是乐观锁的一种实现,用于在数据库并发访问时的情况。去重表这是利用数据库表单的特性来实现幂等。

背景

在软件系统的开发过程中,我们可能有如下需求:

创建业务订单,一次业务请求只能创建一个;

单个订单请求调用支付接口,当遇到网络或系统故障请求重发,也应该只支付一次;

单个订单完成时,给用户发送消息应该只发一次;

等等很多情况下,都需要幂等的特性来支持。

幂等的概念

幂等(idempotence)一词原为数学上的概念,用一个最直观的数学式子表达为:

f(f(x)) = f(x)

对应到软件开发领域,即为同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的,实际上就是接口的可重复调用(包括时间和空间上两个维度)。
不是要求返回值完全相同,而且是指后续多余的调用对系统的数据一致性不造成破坏。对于写入类操作,如果第一次写入是成功的,后续的写入应该抛出异常或者空操作,或者执行了写入但是未对数据造成变化。对于读取类操作,需要保证其实现上是真正的读取,不能在读操作中夹带写操作。

幂等实现方案

幂等性不能脱离业务来讨论。
在不同的需求场景下,实现幂等的思路和方案也会不同,一般有如下通用方案:

1. MVCC(多版本并发控制)

这是乐观锁的一种实现,用于在数据库并发访问时的情况。当数据更新时需要去判断版本号是否一致,如果不一致,则无法对数据进行更新。例如请求支付接口进行扣款时:

update table_name set deposit = deposit-#{payment}, version = version + 1 where orderId = #{orderId} and version = #{version}

这里orderId可进一步设为主键或唯一索引,因为这样是行锁,否则更新操作时会锁表。乐观锁在对已有数据进行更新时既能保证效率,又能保证幂等。

2. 去重表

这是利用数据库表单的特性来实现幂等。以订单请求支付场景为例:
将订单号orderId设为去重表的唯一索引,每次请求支付都根据订单号向去重表中插入一条数据,只有插入成功才继续执行支付操作,相当于在事务的开始阶段加锁。
考虑两种失败的情况:

Insert去重表失败,事务回滚,无任何影响;

Insert去重表成功,支付业务操作失败,事务回滚,删除之前插入去重表的记录,无任何影响;

以上两种失败的情况下,事务的幂等性是可以保持的,避免了单个订单同时多次进行支付的情况。
下图为该支付场景下的时序图:

3. 分布式锁

与去重表思路相同,只是将对数据库的的访问转移到了对缓存(如redis)的访问,提高了效率。具体操作如下:
订单发起支付请求,支付系统会去redis缓存中查询是否存在该订单号orderId的key,如果不存在,则向redis增加key为订单号,然后开始实际支付操作;如果查询到存在该订单号的key,则不进行实际支付操作。无论支付操作成功或失败,在支付操作结果返回后,在缓存中删除该订单号key。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76621.html

相关文章

  • 分布式幂等问题解决方案三部曲

    摘要:解决幂等问题的三部曲,也是作者的思考框架。这是解决幂等问题的第二部曲列出并减少副作用的分析维度。所以在并发执行的维度,将并发重复执行变成串行重复执行是最好的幂等解决方案。 纲要 文章目的:本文旨在提炼一套分布式幂等问题的思考框架,而非解决某个具体的分布式幂等问题。在这个框架体系内,会有一些方案举例说明。文章目标:希望读者能通过这套思考框架设计出符合自己业务的完备的幂等解决方案。文章内容...

    mumumu 评论0 收藏0
  • 【Java】几道常见的秋招面试题

    摘要:总结的时间复杂度是,是空间是使用辅助栈来存储最小值。项目就是为了解决配置繁琐的问题,最大化的实现约定大于配置。 前言 只有光头才能变强 Redis目前还在看,今天来分享一下我在秋招看过(遇到)的一些面试题(相对比较常见的) 0、final关键字 简要说一下final关键字,final可以用来修饰什么? 这题我是在真实的面试中遇到的,当时答得不太好,现在来整理一下吧。 final可以修饰...

    Rocko 评论0 收藏0
  • 翻译连载 | JavaScript 轻量级函数式编程-第5章:减少副作用 |《你不知道的JS》姊妹篇

    摘要:函数式编程者并没有消除所有的副作用。我的结论是这里的并不违反减少或避免副作用的精神。一些语言允许你指定生成随机数的种子。因此,我们必须将内建的随机数生成视为不纯的一方。其他的错误在程序运行期间副作用可能导致的错误是多种多样的。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 关于译者:这是一个流淌...

    yeyan1996 评论0 收藏0

发表评论

0条评论

NikoManiac

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<