首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >在IT领域,什么是幂等性(idempotence)?为什要实现幂等?如何解决幂等性?

在IT领域,什么是幂等性(idempotence)?为什要实现幂等?如何解决幂等性?

作者头像
崔认知
发布于 2024-03-22 03:22:09
发布于 2024-03-22 03:22:09
2K00
代码可运行
举报
文章被收录于专栏:nobodynobody
运行总次数:0
代码可运行

幂等性(idempotence)的定义

幂等性(idempotence)是一个数学和计算机学概念,指的是对于同一操作,无论是一次还是多次执行,产生的结果是一致的,不会因为多次执行而产生副作用。在编程中,幂等操作是指可以使用相同参数重复执行,对系统产生的影响是一样的,即对资源的作用是一样的,不会发生副作用

为什要实现幂等性

在分布式系统和网络通信中,幂等性尤为重要,以防止数据重复或丢失更新问题开发人员在日常开发中必须要考虑幂等性的,尤其是转账、支付等涉及金额交易的场景,如果出现幂等性的问题,造成的后果是非常严重的

非幂等的常见原因

非幂等的重要因素是重复提交引起的,一般情况下,接口调用时都能正常返回信息,不会重复提交,但遇见以下情况时就可能会出现问题,常见的场景如下:

●因网络波动,用户重复提交请求

●用户恶意进行刷单行为

●接口超时重试请求

定时任务重试 ●使用消息队列时,重复消费现象

如何解决幂等性

幂等设计一般有两种处理方法:

(1)需要下游系统提供相关的查询接口。超时业务重试时,先通过接口查询,如果查询到数据,表明上次的调用已经成功,如果失败了就走失败流程。

(2)通过幂等性的方式。也就是这个查询操作交给下游系统,上游系统只管重试,由下游系统保证一次和多次的请求结果是一样的。

幂等的解决方案非常多,需要根据具体的业务场景选择具体策略。

方案一:数据库唯一索引实现幂等性

在保存数据前,可以先select一下数据是否存在。如果数据已存在,则不再写入数据,如果数据不存在,则执行insert操作

但在高并发的场景下,可能会出现两个请求select的时候,都没有查到数据,然后都执行了insert操作,所以此时会有重复数据产生,因此在数据库中,我们需要添加唯一索引来保证幂等

在数据库中,唯一索引是不会引起重复数据的兜底策略。

方案二:防重表机制

防重表机制与唯一索引机制是相同的原理,只不过是单独建一个防重表,防重表也必须引入唯一索引,而且防重表与业务表必须在同一数据库,并且操作要在同一个事务中

防重表机制的主要流程:把唯一主键插入防重表,再进行业务操作,且它们处于同一个事务中。当重复请求时,因为去重表有唯一约束,导致请求失败,可以避免幂等问题。注意去重表和业务表应该在同一个库中,这样就保证了在同一个事务中,即使业务操作失败,也会把去重表的数据回滚。这样可以很好地保证数据的一致性。该方案也是比较常用的,去重表跟业务无关,很多业务可以共用同一个去重表,只要规划好唯一主键即可。

方案三:数据库乐观锁实现幂等性

数据库乐观锁方案适用于执行更新操作,通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号等于数据库表当前版本号,则予以更新,否则认为是过期数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 update account set amount=amount-50,version=version+1 
 
 where id=123 and version = 1;

方案四:悲观锁实现幂等性

悲观锁的实现,往往依靠数据库提供的锁机制,具有强烈的独占和排他特性。

通过mysql 的sql 语句 for update 可以锁住数据;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 select * from account where id = 123 for update;

这里id字段一定要是主键或者唯一索引,不然会锁住整张表,严重影响性能。

方案五:防重Token令牌实现幂等

此方案包含两个请求阶段:

1.客户端请求服务端申请获取token。

2.客户端携带token再次请求,服务端校验token后进行操作。

方案六:分布式锁

分布式锁的逻辑是,每次请求都通过业务唯一ID来尝试获取锁,如果获取成功,就进行后续业务逻辑操作,如果获取失败,就舍弃请求直接返回。

分布式锁通常是基于redis来实现的。

方案六:状态机

很多时候,业务流程是有状态流转的,这个时候可以使用状态机来保证幂等性。

如订单业务中,存在状态「1-已下单,2-已支付,3-已完成,4-已取消」,按照业务流程,状态是依次流转的,所以在update操作时,我们就要根据本次的状态来更新下一次的状态

状态机其实是乐观锁的一种特例。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 update order_info set status = 3 
 
 where id = 123 and status = 2;
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 认知科技技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
从零开始封装 vue 组件
对于学习 Vue 的同学来说,封装 vue 组件是实现代码复用的重要一环。在 Vue 官网中非常详细地介绍了 vue 组件的相关知识,我这里简单摘取使用最频繁的几个知识点,带大家快速入门 vue 组件的使用。
陈树义
2023/12/19
4790
从零开始封装 vue 组件
VUE2快速入门(五)---组件进阶与插槽
数字,字符,布尔值,数组,对象 当带有v-bind:时 会被认为js表达式 如果不加就是单纯的字符串或者数字
代码哈士奇
2021/01/26
4530
VUE2快速入门(五)---组件进阶与插槽
浅学Vue3
NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。2020年3月17日,Github宣布收购npm,GitHub现在已经保证npm将永远免费。
QGS
2024/01/14
4580
vue之vue组件component整理
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
山行AI
2019/07/30
6.9K0
vue之vue组件component整理
Vue组件化开发
1)、我们希望尽可能多的重用代码。   2)、自定义组件的方式不太容易(html、css、js)。   3)、多次使用组件可能导致冲突。   4)、Web Components通过创建封装好功能的定制元素解决上述问题。   5)Vue部分实现了上述Web Components规范。
别先生
2020/04/24
3.2K0
Vue组件化开发
Vue组件基础(下)
指的是:在封装组件时对外界传递过来的props数据进行合法性的校验,从而防止1数据不合法的问题。
岳泽以
2022/10/26
3750
Vue组件基础(下)
Vue的组件
本来还有几个后端知识点要看的,但是我的岗位目前办公处调到上海去了,而且被告知极有可能会做全栈开发...心情复杂... 只能赶紧看看Vue的组件,打包,脚手架问题了. 此去经年只能强大自己,拥抱变化了,上海的毒打会让我更加强壮. 关于本文,我建议如有看到我写的,建议看原版Vue手册,我写的只是整理成我自己最容易理解的方式.
名字是乱打的
2021/12/22
1K0
Vue的组件
Vue之组件化(三)
每个组件的数据都存放在自己的data函数中,不可以直接使用其他组件或Vue实例(根组件)中的data数据。 在开发时,页面中展示的数据都是通过网络请求获取而来的动态数据。因为每个组件都是独立存在,即每个组件中的数据都是独立存储的,那每个组件所需要的动态数据都是通过各自发送网络请求而获取来的吗? 由于组件化的思想,一个完整的页面可以根据功能划分成若干个组件,而这些组件也可以根据逻辑功能再次细分。所以一个页面是由许多个组件集成的。
yuanshuai
2022/08/22
6180
Vue之组件化(三)
Vue-自定义事件之—— 子组件修改父组件的值
如何利用自定义的事件,在子组件中修改父组件里边的值? 关键点记住:三个事件名字 步骤如下: 这里,相对本案例,父组件定义为Second-module,对应的子组件是Three-module 第一步:你
xing.org1^
2018/05/17
1.4K0
Vue父组件与子组件传递事件/调用事件
如上:通过this.$emit()来触发父组件的方法。具体就是子组件触发$emit绑定的事件watchChild,然后父组件监听watchChild,一旦watchChild被触发便会触发父组件的parentReceive方法。
IT工作者
2022/02/17
3.6K0
vue父子组件传值 简单了解vuex
首先呢,需要说说的是,vue既然有双向绑定,那为何会有父子组件之间的传值问题?这个问题也简单,vue的组件会供其他的vue页面进行调用,如果数组都是双向绑定的话,那么就容易混乱了,比如a,b页面绑了一个num=10,那b,c页面又绑了num=5,那vue实例的num到底听谁的?所以,这就是vue官网为什么说
全栈程序员站长
2022/08/29
4740
Vue3学习笔记(四)——组件、生命周期
如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展,但如果,我们将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。如果我们将一个个功能块拆分后,就可以像搭建积木一下来搭建我们的项目。
张果
2022/11/14
1.5K0
Vue3学习笔记(四)——组件、生命周期
详解vue组件三大核心概念
本文主要介绍属性、事件和插槽这三个vue基础概念、使用方法及其容易被忽略的一些重要细节。如果你阅读别人写的组件,可以从这三个部分展开,它们可以帮助你快速了解一个组件的所有功能。
Nealyang
2019/09/29
1.4K0
详解vue组件三大核心概念
Vue.js 组件间的数据传递方法
这种应该是 vue.js 中最常见也是最为自然的一种方式了,要求我们在子组件中声明 props 然后在父组件中为子组件的 prop 赋值。
初代庄主
2022/03/30
6.3K0
Vue.js 组件间的数据传递方法
Vue3 | 父子组件间通信、组件间双向绑定的高级内容、插槽详解、动态组件、异步组件
前面的笔记 —— 《Vue3 | 组件的定义及复用性、局部组件、全局组件、组件间传值及其校验、单项数据流、Non-props属性》,单向数据流的概念, 即子组件无法修改来自父组件的数据字段, 如果确要修改,可以使用下面说的方式进行通信: 首先,在子组件的UI点击回调方法中,调用this.$emit('【自定义事件名】'), 向外发送一个事件; 接着各级父组件会收到这个事件, 则在父组件中 调用 子组件标签处, 以 @【事件名】= "回调方法名"的形式,监听该事件以及配置回调方法; 回调方法中即可 对 子组件意图修改 的 父组件数据字段 进行修改;
凌川江雪
2021/03/23
6.5K0
Vue3 | 父子组件间通信、组件间双向绑定的高级内容、插槽详解、动态组件、异步组件
Vue 组件通信的 8 种方式
[3245a3c0598b4b79b32f60649ded9cca~tplv-k3u1fbpfcp-watermark.image] 前言     做了半年的公司系统,终于就在前天上线了。后期改BUG时间拖得太长了,出现的大部分BUG 是 前端 与后端 信息不对称导致的,逻辑性错误很不多,用户体验上稍微差点,毕竟第一次做这么大的系统(100w+),通过这次系统的开发,总结了不少经验,如何更好的跟后端人员协作开发以及如何设计来提高用户体验上,之前自己做开发没关注这方面,只注重功能实现,后期的这块多补补。
程序员海军
2022/02/15
4180
Vue 组件通信的 8 种方式
Vue—前端框架
3、在外部可以通过vue对象名.属性的方式获取属性值,在vue对象内部,通过this.属性的方式获取属性值
nbsp-nbsp
2020/01/15
7.9K0
Vue.js——组件快速入门(下篇)
上一篇我们重点介绍了组件的创建、注册和使用,熟练这几个步骤将有助于深入组件的开发。
Vincent-yuan
2020/07/08
10.3K0
Vue.js——组件快速入门(下篇)
7个 Vue3 中的组件通信方式
本文采用<script setup />的编写方式,比options API更自由。然后我们会讲以下七种组件通信方式:
唐志远
2022/10/27
7940
7个 Vue3 中的组件通信方式
Vue组件通信探究之子组件向父组件传递数据
在Vue.js应用中,组件通信是一个不可忽视的话题。除了父组件向子组件传递数据外,还存在一种常见的场景:子组件向父组件传递数据。本文将详细介绍Vue中子组件向父组件传递数据的实现方式,并通过实际例子演示这一过程。
用户10781437
2023/10/10
4450
推荐阅读
相关推荐
从零开始封装 vue 组件
更多 >
交个朋友
加入[数据] 腾讯云技术交流站
获取数据实战干货 共享技术经验心得
加入数据技术工作实战群
获取实战干货 交流技术经验
加入[数据库] 腾讯云官方技术交流站
数据库问题秒解答 分享实践经验
换一批
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验