幂等性常用的解决方案

2023-11-18

幂等性常用的解决方案


在进行讲解方案之前,我想先说一下什么是幂等性,下面是我用自己的理解说的,不是专业的术语,对于同样的多次请求,只会对第一次请求进行处理,多次请求返回的结果是相同的。

​ 幂等性的专业术语如下(选自百度百科)

幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。
在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“setTrue()”函数就是一个幂等函数,无论多次执行,其结果都是一样的.更复杂的操作幂等保证是利用唯一交易号(流水号)实现。

方案一、乐观锁

​ 使用乐观锁的话,我们需要在数据库中设计一个用来作为版本号的字段,比如增加一个timeStamp或者version字段来作为数据库的字段,我们在每次更新操作的时候会判断这个版本号,只有版本号是一致的才可以进行更新,否则是无法进行更新的。

​ 比如下面的sql流程

#1.查询我们要操作的数据,获得当前这行数据的版本号
select id,money,version from user where id=1;
#2.根据第一步获得的版本号来进行更新操作。
update user set money=money-100,version=version+1 where id=1 and version=1;

​ 如果此时返回的结果是1说明操作成功了,如果返回的数据是0的话,说明当前这个请求没有进行处理。通过这个乐观锁保证了多个请求同时过来的时候只有一个请求可以执行。同时为了保证幂等性,如果返回的结果是0的话,我们也要返回成功的结果,因为幂等性要保证多次请求返回的结果是相同的。

​ 流程图如下:

方案二、加唯一索引

​ 加唯一索引可以保证同时有多个请求过来的时候只有一个请求可以执行插入操作,因为当一个请求已经插入了数据之后,其他请求再去插入数据的时候因为有唯一索引所以就会报错。为了保证幂等性,如果一个请求得到的结果是报错的话,我们后端要对这种异常进行处理来保证给前端返回的结果是请求成功,因为要保证多次请求返回的结果是一样的。

​ 但是唯一索引的添加也是一个技术活,如果我们对一个单一的字段设置为唯一索引的话,如果你的这个业务场景种可以进行数据的真正删除的话那么这么设计是没有问题的,但是如果你的业务中要求你的数据不能真正的删除而是需要进行留档,用户的删除只是进行逻辑删除的话,我们设计的单一的字段为唯一索引的话,那么我们插入新数据的时候就会出现唯一索引冲突的问题了。

​ 那么对于这种业务场景我们就要采用符合索引了,也就是将多个 字段作为唯一索引,比如我们将order_id和is_delete字段作为一个唯一索引。但是这种设计也是有问题的,比如如果我们的系统中的逻辑删除字段(is_delete)的值只有0和1,0代表没有删除,1代表删除了,那么这样的话,我们再插入新的数据的时候还是会出现唯一索引冲突的。那么解决这个问题的方案是什么呢?那就是我们可以扩大is_delete字段的值,比如如果这个字段已经删除了我们将is_delete的值设置为这一行数据的唯一主键id,如果没有删除的话就是0.那么这样的话就不会出现唯一索引冲突了。

​ 加唯一索引方案的流程图

方案三、利用状态机

​ 状态机可能看起来和乐观锁有点一样,但是有一个关键的区别,乐观锁的版本号是无界的,而状态机一般都是有边界的。而且如果你想要利用状态机来实现幂等性的话,一般是你的数据表中有状态这个字段,而且状态的变化是递增的,比如0是下单 1是已支付 2是完成支付。那么你的请求可以根据你数据表中的这个状态字段来进行更新操作。比如你想要将订单由已支付变成完成支付,你可以使用下面的sql语句

update user set status=2 where id=1 and status=1

第一次请求的时候你的状态是1是可以正常执行,将状态变成2的,后面再过来的请求再执行相同的sql的时候status就不是1了,就无法执行这个语句了。通过这种状态机的机制,就可以保证多个请求过来的时候只有第一个请求可以成功执行,后面过来的请求是会报错的,但是为了保证幂等性你需要将后面的请求返回给前端执行成功的结果。

​ 利用状态机方案的流程图

方案四、加分布式锁

​ 现在比较常用的分布式锁的框架就是Redis和zookeeper了。下面我来说一下redis中的方法。

​ 1.setnx命令

​ 2.set命令

​ 3.redisson

​ 多个请求过来的时候我们只让第一个请求可以设置key,并且给这个key设置一个过期时间,后面再过来的请求发现已经有这个key了就无法设置key了。所以成功设置了key的请求就是成功执行的那个请求,后面没有成功设置key的请求就是没有成功执行的请求,但是我们还是要给前端返回成功的结果,因为要保证幂等性嘛。

​ zookeeper的解决方案的话,使用Curator框架就可以了。

​ 分布式锁方案的流程图

方案五、获取token

​ 获取token的方案也是需要借助于Redis的。大体的流程是这样的,当前端发过来一个请求之后,后端会生成一个token,后端将这个token发送给前端,同时保存到redis中同时要记得设置过期时间。然后前端的每次请求都要携带这个token,如果是第一次发过来请求,那么将这个token从redis中删除。后序的请求携带了这个token过来,后端去redis中查询发现没有了这个token就意味着这不是第一次请求而是重复的请求,就不会执行,但是还是要给前端返回成功的结果,来保证幂等性。

​ 同时需要注意的一点就是,第一个请求来的时候查询redis中的token和删除这个token我们要使用lua脚本来封装成一个原子操作,这样才能保证只有第一个请求能够处理。

​ 使用获取token方案的流程图

​ 第二步,做具体业务操作

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

幂等性常用的解决方案 的相关文章

  • @TableGenerator 的初始值属性在 Hibernate 中显示问题,但在 JPA 中则不然

    package com sb firstjpaexample pojo import javax persistence Column import javax persistence Entity import javax persist
  • 如何在 IDEA Intellij 上使用 Spring-boot 自动重新加载

    我写了一个基于Spring boot tomcat freemarker的项目 我运行成功 但是每当我修改一些模板和java类时 我必须重新启动服务器或使用Intellij上的 重新加载更改的类 菜单才能使更改生效 浪费很多时间 然后我尝试
  • 在 Java 中使用 Batik 检查和删除 SVG 中的属性

    这个问题基本上说明了一切 如何检查 SVG 是否具有 viewBox 属性 我正在使用蜡染库 我需要这个 因为我需要 至少 通知用户有一个 viewBox 属性 我可以删除它吗 使用 org w3c dom 类 您可以按照以下方式做一些事情
  • 在 jTextfield 中禁用“粘贴”

    我有一个用 Swing awt 编写的应用程序 我想阻止用户将值粘贴到文本字段中 有没有办法在不使用动作监听器的情况下做到这一点 您可以使用 null 参数调用 setTransferHandler 如下所示 textComponent s
  • 对象数组的数组(二维数组)JNI

    我正在努力创建自定义对象类型 ShareStruct 的二维数组 jobjectArray ret jobjectArray ins jobjectArray outs jclass myClass env gt FindClass env
  • 如何作为应用程序发布到页面?

    所以 我有一个应用程序 Facebook 应用程序实体 并且我有一个页面 我想使用应用程序通过java代码 通过restfb或任何其他建议 发布到页面 看起来我错过了页面授予应用程序发布权限的阶段 不知道该怎么做 谢谢你们 乌里 您只能 作
  • 使用 Apache POI Excel 写入特定单元格位置

    如果我有一个未排序的参数 x y z 列表 是否有一种简单的方法将它们写入使用 POI 创建的 Excel 文档中的特定单元格 就好像前两个参数是 X 和Y 坐标 例如 我有如下行 10 4 100 是否可以在第 10 行第 4 列的单元格
  • 最快的高斯模糊实现

    如何以最快的速度实施高斯模糊 http en wikipedia org wiki Gaussian blur算法 我要用Java来实现它 所以GPU http en wikipedia org wiki Graphics processi
  • 迭代函数可以调用自身吗?

    当观看下面的 MIT 6 001 课程视频时 讲师在 28 00 将此算法标记为迭代 但是 在 30 27 他说这个算法和实际的 递归 算法都是递归的 该函数正在使用基本情况调用自身 那么这次迭代情况如何 private int itera
  • 使用 Spring 控制器处理错误 404

    I use ExceptionHandler处理我的网络应用程序抛出的异常 在我的例子中我的应用程序返回JSON回应HTTP status用于对客户端的错误响应 但是 我正在尝试弄清楚如何处理error 404返回与处理的类似的 JSON
  • 无法访问“不安全”java方法的java表达式语言

    我正在开发一个项目 让用户向服务器提交小 脚本 然后我将执行这些脚本 有很多脚本语言可以嵌入到Java程序中 例如mvel ognl uel clojure rhino javascript等 但是 据我所知 它们都允许脚本编写者调用Jav
  • 我需要在 JFileChooser(打开模式)中显示不带扩展名的文件名。如何?

    我在打开模式下使用 JFileChooser 我需要显示不带扩展名的 文件名 字段 如何 我知道文件视图 它删除文件系统文件中的扩展名 但将所选文件中的扩展名保留在 文件名 字段中解释 http saveimg ru show image
  • 记录共享和映射的诊断上下文

    据我所知 其他人做了什么来解决 Commons Logging 项目 针对 NET 和 Java 不支持映射或嵌套诊断上下文这一事实 执行摘要 我们选择直接使用实现者日志框架 在我们的例子中为 log4j 长答案 您是否需要一个抽象日志框架
  • 以有效的方式从 Map 中删除多个键?

    我有一个Map
  • java setFullScreenWindow 在 Mac 中隐藏登录对话框

    我使用的是全屏窗口 类似于屏幕保护程序 使用这里的方法 GraphicsEnvironment getLocalGraphicsEnvironment getDefaultScreenDevice setFullScreenWindow t
  • 拆分/标记化/扫描字符串并注意引号

    Java中是否有默认 简单的方法来分割字符串 但要注意引号或其他符号 例如 给定以下文本 There s a man that live next door in my neighborhood and he gets me down Ob
  • 在 java 中运行外部应用程序但不要等待它完成

    我正在用java编写一个应用程序 允许我运行其他应用程序 为此 我使用了 Process 类对象 但当我这样做时 应用程序会等待进程结束 然后再退出 有没有办法在 Java 中运行外部应用程序 但不等待它完成 public static v
  • 使用单独的线程在java中读取和写入文件

    我创建了两个线程并修改了 run 函数 以便一个线程读取一行 另一个线程将同一行写入新文件 这种情况会发生直到整个文件被复制为止 我遇到的问题是 即使我使用变量来控制线程一一执行 但线程的执行仍然不均匀 即一个线程执行多次 然后控制权转移
  • java中使用多线程调用同一类的不同方法

    我有一个类 如下所示 具有三种方法 public class MyRunnable implements Runnable Override public void run what code need to write here to c
  • 如何使用自定义 JDK 构建 Jenkins 项目?

    我有一个常规的 Jenkins 实例 运行一些多分支管道 该实例在 JDK 11 上运行 因为 Jenkins 并不真正支持更高版本 没关系 但不好的是 我的所有管道似乎也都受到 Java 11 的限制 Jenkins 仅使用它自己也使用的

随机推荐

  • 使用正则表达式爬虫抓取猫眼电影排行Top100

    目标站点分析 分析网址 首页 https maoyan com 点击榜单 https maoyan com board 点击Top100 https maoyan com board 4 目标站点为 https maoyan com boa
  • 工具 - windows(PowerShell) 常用命令

    1 拷贝cp命令 例子 PS D Project test jni gt cp libs arm64 v8a NetU VTest app src main jniLibs Recurse Force 备注 Recurse 递归到子目录 F
  • vuescroll-一款基于vuejs2.x的虚拟滚动条

    介绍 Vuescroll 一个功能强大 有多种模式的基于Vue js的滚动条插件 它的原理是创建 div 用于包裹要滚动的内容 操后操作容器的样式或者scrollTop或scrollLeft完成内容的滚动 设计它的目的是用来美化和增强你的滚
  • 2023年3月股份行GX评测盘点:招商银行稳居榜首,各项指标均居前列

    易观 2023 年3月GX评测数据显示 招商银行 平安口袋银行 中信银行位居行业Top 10 浦发银行 兴业银行 光大银行紧跟其后 股份行APP 用户体验 招商银行以绝对优势稳居第一 2023年3月股份行GX评测结果数据显示 在操作体验方面
  • Google的TCP BBR拥塞控制算法深度解析

    原作者 dog250 授权发布 重新整理 极客重生 hi 大家好 今天推荐一篇我认为在TCP BBR技术里面分析非常透彻的文章 希望大家可以学习到一些真正的知识 理解其背后的设计原理 才能应对各种面试和工作挑战 宏观背景下的BBR 1980
  • 利用Python进行简单的图像识别(验证码)

    这是一个最简单的图像识别 将图片加载后直接利用Python的一个识别引擎进行识别 将图片中的数字通过 pytesseract image to string image 识别后将结果存入到本地的txt文件中 1 encoding utf 8
  • csol2服务器维护中 无法登陆游戏,csol2现在怎么登不上去?为什么?说服务...

    2016 07 08 00 48龚宁静 客户经理 CSOL金勋怎么抽的第一个建议 卡延迟 看过好多人分享经验说卡延迟出金的几率会很大 本人也有些体会 我家是10M的光纤 跟我开金少有关系 我想有很大关系 因为在活动期间 那屏刷的真叫一个快
  • Android开启和关闭护眼模式

    Android开启和关闭护眼模式 在现代社会中 我们经常长时间使用智能手机或平板电脑等电子设备 长时间盯着屏幕可能会对眼睛造成疲劳和不适 为了保护用户的眼睛健康 许多移动设备都提供了护眼模式 本文将介绍如何在Android设备上开启和关闭护
  • Element中的el-tree组件的懒加载和手动更新节点数据

  • 安装Windows10系统后,CPU 不再支持虚拟化解决方案

    小米的游戏本 之前是支持虚拟化的 安装过好几次虚拟机 最近重新安装了Windows10系统后 CPU不再支持虚拟化了 具体表现为安装VMWare失败 解决方案 小娜搜索并打开 启用或关闭Windows功能 把Hyper V的勾选去掉 因为它
  • Vue前端开发中的输入限制与输入规则探究

    前言 在Vue前端开发中 我们经常需要对用户的输入进行限制和规范 以确保数据的准确性和安全性 本文将介绍如何使用Vue的el input组件来实现输入限制和输入规则 并提供相应的代码示例 一 输入限制 最大长度限制 我们可以使用maxlen
  • 如何快速增加大量用户和用户组

    Windows平台下 假设建有Domain A和Domain B 两者已经建立了信任关系 可以采用在命令行中输入如下命令在各自的domain中增加用户或用户组 1 增加用户组FOR L i in 1 1 10 DO dsadd group
  • 神经网络与深度学习笔记——代价函数,规范化,过拟合

    神经网络与深度学习笔记系列一共有五个专题 分别是第一章使用神经网络识别手写数字 梯度下降算法是什么 主要介绍了神经网络的基础例如感知器激活函数等概念 最主要介绍了梯度下降算法 第二章反向传播算法如何工作 反向传播算法原理 主要介绍了反向传播
  • 数据结构--二叉树-堆(1)

    文章目录 树 概念 相关的基本概念 树的表示 二叉树 概念 特殊二叉树 性质 堆 二叉树的顺序结构 堆的概念 堆的实现 初始化 数组初始化为堆 向上调整 向下调整 插入 删除 打印 摧毁 判空 获取堆顶数据 验证 堆的应用 堆排序 TopK
  • 磁盘测试工具FIO

    磁盘测试工具FIO https www cnblogs com klb561 p 11939355 html 目前主流的第三方IO测试工具有fio iometer和Orion 这三种工具各有千秋 fio在Linux系统下使用比较方便 iom
  • 淘宝官方订单API接口,获取售出的商品订单列表(爬虫数据)

    淘宝 天猫获取售出的商品订单列表 API 返回值说明 seller order list 获取售出的商品订单列表 公共参数 名称 类型 必须 描述 key String 是 调用key 必须以GET方式拼接在URL中 获取Key和secre
  • 大学英语六级历年真题Word,PDF,和音频 下载

    1 链接 https pan baidu com s 11w bAM1JoHTt HjNfor70g 提取码 ro6w 复制这段内容后打开百度网盘手机App 操作更方便哦 1 1 1 1 1 下载方式 扫码联系获取 1学习人工智能可以扫码关
  • C++函数指针定义及用法

    什么是函数指针 如果在程序中定义了一个函数 那么在编译时系统就会为这个函数代码分配一段存储空间 这段存储空间的首地址称为这个函数的地址 而且函数名表示的就是这个地址 既然是地址我们就可以定义一个指针变量来存放 这个指针变量就叫作函数指针变量
  • Windows游戏加速外挂-变速齿轮 学习笔记-【第一篇】

    找到两篇文章 是比较流行的方法 接下来记录一下收获 第一篇文章 变速齿轮 研究手记 转自 http www newasp net tech 58262 html 注意 如果你看了本文 对我们这个软件有兴趣 请到我们的主页www vrbrot
  • 幂等性常用的解决方案

    幂等性常用的解决方案 在进行讲解方案之前 我想先说一下什么是幂等性 下面是我用自己的理解说的 不是专业的术语 对于同样的多次请求 只会对第一次请求进行处理 多次请求返回的结果是相同的 幂等性的专业术语如下 选自百度百科 幂等 idempot