热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

深入理解幂等技术

幂等(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可以标识这一批小任务属于同一笔业务;另一方便,小任务名可以区分不同的小任务。


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


推荐阅读
  • Centos下安装memcached+memcached教程
    本文介绍了在Centos下安装memcached和使用memcached的教程,详细解释了memcached的工作原理,包括缓存数据和对象、减少数据库读取次数、提高网站速度等。同时,还对memcached的快速和高效率进行了解释,与传统的文件型数据库相比,memcached作为一个内存型数据库,具有更高的读取速度。 ... [详细]
  • 分库分表  ShardingJDBC (详解 1/6)
    狂创客圈经典图书:《NettyZookeeperRedis高并发实战》面试必备+面试必备+面试必备【博客园总入口】疯狂创客圈经典图书:《SpringCloud、Nginx高并发核心 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 数据库锁的分类和应用
    本文介绍了数据库锁的分类和应用,包括并发控制中的读-读、写-写、读-写/写-读操作的问题,以及不同的锁类型和粒度分类。同时还介绍了死锁的产生和避免方法,并详细解释了MVCC的原理以及如何解决幻读的问题。最后,给出了一些使用数据库锁的实际场景和建议。 ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • Java开发实战讲解!字节跳动三场技术面+HR面
    二、回顾整理阿里面试题基本就这样了,还有一些零星的问题想不起来了,答案也整理出来了。自我介绍JVM如何加载一个类的过程,双亲委派模型中有 ... [详细]
  • go语言能做什么?很多朋友可能知道Go语言的优势在哪,却不知道Go语言适合用于哪些地方。1、Go语言作为服务器编程语言,很适合处理日志、数据打包、虚拟机处理、文件系统、分布式系统、 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 2021最新总结网易/腾讯/CVTE/字节面经分享(附答案解析)
    本文分享作者在2021年面试网易、腾讯、CVTE和字节等大型互联网企业的经历和问题,包括稳定性设计、数据库优化、分布式锁的设计等内容。同时提供了大厂最新面试真题笔记,并附带答案解析。 ... [详细]
  • 开发笔记:读《分布式一致性原理》JAVA客户端API操作2
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了读《分布式一致性原理》JAVA客户端API操作2相关的知识,希望对你有一定的参考价值。创 ... [详细]
  • 新手学习java中,Java新手
    本文目录一览:1、java初学者怎么入门2、新 ... [详细]
  • HadoopYARN集群是一个通用的资源管理平台,可为各类计算框架提供资源的管理和调度。其核心是通过一个全局的资源管理器来实现分离资源管理与作业调度监控。Hadoop ... [详细]
  • 机械硕士,因实验室师兄毕业拿5K,自学Java转型大数据
    个人情况我是本硕机械专业,毕业半年,最初接触java是由于研二的时候,看到了实验室师兄们找工作那个艰难啊,硕士毕业最少的拿了 ... [详细]
  • dubbo学习 一 dubbo概述
    1,背景1,网站刚开时候的时候可能所有的功能业务都在一个应用里面2,当业务不断复杂,流量不断增多的时候,就需要将原先的一个应用划分成多个独立的应用。3,当分出来的业务越来越多的时候 ... [详细]
author-avatar
宝贝缘缘儿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有