深入理解幂等技术

栏目: 数据库 · 发布时间: 5年前

内容简介:幂等(idempotent)是一个数学与计算机学概念,常见于抽象代数中。在编程中,一个幂等操作的特点是,其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。幂等函数可以改变系统的状态。例如,幂等的场景有很多,例如:

什么是幂等

幂等(idempotent)是一个数学与计算机学概念,常见于抽象代数中。

在编程中,一个幂等操作的特点是,其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。幂等函数可以改变系统的状态。例如, setTrue() 就是一个幂等函数,因为无论执行多少次,其结果都是一样的。

幂等的场景有很多,例如:

  • 前端重复提交选中的数据,后台只产生对应这个数据的一个反应结果;
  • 我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱;
  • 发送消息,也应该只发一次,同样的短信发给用户,用户会崩溃;
  • 创建业务订单,一次业务请求只能创建一个,创建多个就会出大问题。

幂等的技术手段

幂等并不是并发场景下的特有问题。幂等处理的是多次执行的问题,而并发仅仅是多次执行的一种形式。不管是依次执行,还是并发执行,都需要做好幂等。有些技术人员将解决并发问题的技术手段,例如悲观锁、乐观锁和分布式锁,当成幂等的技术手段,这是不对的。

再次强调,幂等的核心是确保唯一性。

唯一索引

在数据库中建立唯一索引,用作幂等记录,可以防止插入重复的数据。 在幂等函数中,先执行一次查询操作,如存在幂等记录则返回第一次执行的结果,如不存在幂等记录则继续执行。在并发场景下,可能存在多个线程同时插入幂等记录,这时候唯一索引可以确保只有一个线程插入成功,其它线程抛出异常。

除了插入幂等记录,应该还要插入其它的业务数据,这个时候务必使用事务。在实际工作中,幂等记录与事务经常同时出现,如影相随。

唯一数据

使用 redis 、memcache和zookeeper都可以实现唯一数据,这里仅用redis的SETNX举例。笔者从redis的官方文档摘抄了SETNX的用法,如下所示。

SETNX key value

将 key 的值设为 value ,当且仅当 key 不存在。

若给定的 key 已经存在,则 SETNX 不做任何动作。

SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。

可用版本:
>= 1.0.0
时间复杂度:
O(1)
返回值:
设置成功,返回 1 。
设置失败,返回 0 。
复制代码

在幂等函数中,将唯一标识作为key,任取value,调用SETNX。如果返回1,说明当前是第一次执行,继续执行幂等函数;如果返回0,取出第一次执行的结果并返回给调用方。在并发场景下,可能因尚未完成第一次执行而取不到结果,这时候可以稍作等待。

除了redis、memcache和zookeeper,还有其它手段可以实现唯一数据,读者可自行探索。只要可以实现唯一数据,就可以用来做幂等。

状态机约束

在单据相关的业务,或者是任务相关的业务,基本会涉及到状态机。业务单据上面有个状态,这个状态根据一个有限状态机进行跳转。如果状态机已经处于下一个状态,这时候是不能往回跳转到上一个状态的。通过状态机的跳转约束,可以做到有限状态机的幂等。

幂等的场景

幂等经常与事务同时出现,而事务适合小任务场景、不适合大任务场景,因此笔者将幂等场景分为以下两类进行介绍。为了方便描述,我们假设bizId可以唯一标识一笔业务。

小任务场景

这个场景的处理方式很简单,可以追求强一致性。在幂等函数中,先判断幂等记录是否存在。如果存在,直接返回;如果不存在,开启一个事务。在事务中,采用任务名+bizId作为幂等组合字段,插入幂等记录和业务数据。它的流程图如下。

深入理解幂等技术

大任务场景

在大任务场景下,需要将大任务拆成多个小任务分别执行。在每个小任务中,都可以有事务。但是,没有事务保证所有的小任务同时成功。因此,存在部分成功的场景。针对部分成功的场景,可以利用重试机制做到最终一致性。重试机制意味着多次执行,回到了幂等问题。这里只介绍需要幂等的场景。如果同时存在需要幂等和不需要幂等的场景,请加入一个判断标。

同步执行小任务

同步执行小任务的流程图如下。各小任务依次执行,中间的小任务不返回结果,仅在最后一个小任务或之后返回结果。

深入理解幂等技术

异步执行小任务

异步执行小任务的流程图如下。各小任务单独执行,互相不感知,也没有地方返回结果。

深入理解幂等技术

幂等字段

不管是同步执行小任务,还是异步执行小任务,都需要为每个小任务设置一个幂等字段或幂等组合字段。笔者推荐采用 小任务名+bizId 作为幂等组合字段。一方面,bizId可以标识这一批小任务属于同一笔业务;另一方便,小任务名可以区分不同的小任务。


以上所述就是小编给大家介绍的《深入理解幂等技术》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java Servlet & JSP Cookbook

Java Servlet & JSP Cookbook

Bruce W. Perry / O'Reilly Media / 2003-12-1 / USD 49.99

With literally hundreds of examples and thousands of lines of code, the Java Servlet and JSP Cookbook yields tips and techniques that any Java web developer who uses JavaServer Pages or servlets will ......一起来看看 《Java Servlet & JSP Cookbook》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具