我们实际系统中有很多操作,是不管做多少次,都应该产生一样的效果或返回一样的结果。例如 1. 前端重复提交选中的数据,应该后台只产生对应这个数据的一个反应结果;2. 我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统 bug 重发,也应该只扣一次钱;3. 发送消息,也应该只发一次,同样的短信发给用户,用户会哭的;4. 创建业务订单,一次业务请求只能创建一个,创建多个就会出大问题等等很多重要的情况都需要幂等的特性来支持。

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

1.查询操作

查询一次和查询多次,在数据不变的情况下,查询结果是一样的。select 是天然的幂等操作;

2.删除操作

删除操作也是幂等的,删除一次和多次删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在,返回 0,删除的数据多条,返回结果多个

3.唯一索引

防止新增脏数据。比如:支付宝的资金账户,支付宝也有用户账户,每个用户只能有一个资金账户,怎么防止给用户创建资金账户多个,那么给资金账户表中的用户 ID 加唯一索引,所以一个用户新增成功一个资金账户记录。要点:唯一索引或唯一组合索引来防止新增数据存在脏数据(当表存在唯一索引,并发时新增报错时,再查询一次就可以了,数据应该已经存在了,返回结果即可

4.token 机制

防止页面重复提交。业务要求:页面的数据只能被点击提交一次;发生原因:由于重复点击或者网络重发,或者 nginx 重发等情况会导致数据被重复提交;解决办法:集群环境采用 token 加 redis(redis 单线程的,处理需要排队);单 JVM 环境:采用 token 加 redis 或 token 加 jvm 内存。处理流程:1. 数据提交前要向服务的申请 token,token 放到 redis 或 jvm 内存,token 有效时间;2. 提交后后台校验 token,同时删除 token,生成新的 token 返回。token 特点:要申请,一次有效性,可以限流。注意:redis 要用删除操作来判断 token,删除成功代表 token 校验通过,如果用 select+delete 来校验 token,存在并发问题,不建议使用

5.悲观锁

获取数据的时候加锁获取。

select * from table_xxx where id='xxx' for update;

注意:id 字段一定是主键或者唯一索引,不然是锁表,会死人的悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用

乐观锁只是在更新数据那一刻锁表,其他时间不锁表,所以相对于悲观锁,效率更高。乐观锁的实现方式多种多样可以通过 version 或者其他状态条件:

  1. 通过版本号实现

update table_xxx set name=#name#,version=version+1 where version=#version#

如下图(来自网上):

2.通过条件限制

update table_xxx set avai_amount=avai_amount-#subAmount# where avai_amount-#subAmount# >= 0

要求:quality-#subQuality# >= ,这个情景适合不用版本号,只更新是做数据安全校验,适合库存模型,扣份额和回滚份额,性能更高

7.分布式锁

还是拿插入数据的例子,如果是分布是系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁,通过第三方的系统(redis 或 zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁,这样其实是把多线程并发的锁的思路,引入多多个系统,也就是分布式系统中得解决思路。要点:某个长流程处理过程要求不能并发执行,可以在流程执行之前根据某个标志(用户 ID+后缀等)获取分布式锁,其他流程执行时获取锁就会失败,也就是同一时间该流程只能有一个能执行成功,执行完成后,释放分布式锁(分布式锁要第三方系统提供)

8.select + insert

并发不高的后台系统,或者一些任务 JOB,为了支持幂等,支持重复执行,简单的处理方法是,先查询下一些关键数据,判断是否已经执行过,在进行业务处理,就可以了。注意:核心高并发流程不要用这种方法

9.状态机幂等

在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机(状态变更图),就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,这时候,如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。注意:订单等单据类业务,存在很长的状态流转,一定要深刻理解状态机,对业务系统设计能力提高有很大帮助

10.对外提供接口的 api 如何保证幂等

如银联提供的付款接口:需要接入商户提交付款请求时附带:source 来源,seq 序列号。

source+seq 在数据库里面做唯一索引,防止多次付款(并发时,只能处理一个请求) 。重点:对外提供接口为了支持幂等调用,接口有两个字段必须传,一个是来源 source,一个是来源方序列号 seq,这个两个字段在提供方系统里面做联合唯一索引,这样当第三方调用时,先在本方系统里面查询一下,是否已经处理过,返回相应处理结果;没有处理过,进行相应处理,返回结果。注意,为了幂等友好,一定要先查询一下,是否处理过该笔业务,不查询直接插入业务系统,会报错,但实际已经处理了

解决幂等性问题方法大全相关推荐

  1. VueJS项目报错解决:router.map is not a function - 方法大全

    VueJS项目报错解决:router.map is not a function - 方法大全 问题描述: vue报错 router.map is not a function 原因和解决办法(2种以 ...

  2. idea连接不了5.6mysql_IDEA无法连接mysql数据库的6种解决方法大全

    本文主要介绍了IDEA无法连接mysql数据库的6种解决方法大全,分享给大家,具体如下: 1.本地的mysql没有创建该数据库(笔者就是这个原因!) 查看数据库发现没有,重建就可以了 测试成功! 网上 ...

  3. 瑞友客户端无法建立跟远程计算机的连接,瑞友天翼终端错误信息的原因以及解决方法大全.doc...

    瑞友天翼终端错误信息的原因以及解决方法大全 终端错误信息的原因以及解决办法大全 由于在数据加密中存在错误,此会话将结束.请尝试重新连接到远程计算机. 原因: 数据加密为在网络连接上进行数据传输提供了安 ...

  4. html没有注册类,电脑提示没有注册类别的解决方法大全

    电脑提示没有注册类别怎么办?在使用电脑的过程中,我们最常遇到的就是没有注册类别的问题,大多都是在打开软件的时候遇见这种错误提示,那么win7系统提示没有注册类别怎么办呢?下面小编就为大家介绍电脑提示没 ...

  5. iphone手机显示itunes store无法连接服务器,iPhone无法连接到iTunes Store解决方法大全...

    核心提示:那iPhone无法连接到iTunes Store怎么办呢?今天小编会通过这篇文章来告诉大家遇到这种问题时该如何解决. iPhone无法连接到iTunes Store解决方法大全 最近很多果粉 ...

  6. win7电脑连接无线网络怎么连接服务器未响应,Win7无线网络无法连接的原因及Wifi无法连接解决方法大全...

    目前无线网络连接已经是大家使用的设备连接网络的主要方式,然而很多朋友在使用Win7系统笔记本或是电脑时会遇到Win7无线网络无法连接的问题,无线网络无法连接的原因其实有很多种,解决方法也要根据故障的原 ...

  7. 苹果手用计算机解锁手机密码,苹果手机密码忘了怎么解锁(解决方法大全)

    那么,苹果手机忘记解锁密码怎么办?下面,小编就为大家整理了苹果手机忘记解锁密码的解决方法大全. iPhone解锁密码一般是4位或6位,如果忘记了密码,可以通过抹掉设备的方式恢复,但也会导致iOS设备数 ...

  8. mysql 增删改查时的错误解决方法大全

    mysql 增删改查时的错误解决方法大全     信息1:Error: Access denied for user: 'linanma@localhost' (Using password: YES ...

  9. 苹果手用计算机解锁手机密码,苹果手机忘记解锁密码怎么办?解决方法大全

    原标题:苹果手机忘记解锁密码怎么办?解决方法大全 目前,很多苹果手机用户都是使用指纹解锁,所以,如果突然要使用解锁密码进行苹果手机解锁的话,很多苹果手机用户会想不起来苹果手机的解锁密码.那么,苹果手机 ...

最新文章

  1. linux重启was控制台报错,Linux非WAS部署,启动报错Cannot run program \lsb_release\
  2. 联想T430i安装Win7
  3. 韦博英语危机爆发,教培行业如何应对中年危机?
  4. signature=35e01da53254eb12b5fc3c020f572e6a,Signature Analyzer Use NXP MCU
  5. WEB前端 vue学习一使用 vue-cli 搭建项目
  6. nginx-配置基于ip或域名的虚拟主机
  7. Matlab在坐标点上按顺序标序号
  8. 可持久化数据结构、可并堆
  9. 12. Qt中相关字符串处理
  10. Github标星35K+超火的Spring Boot实战项目(附项目地址+教程文档)
  11. Oracle SQL Developer 调试存储过程步骤(Oracle)
  12. 【优化选址】基于matlab蚁群算法求解电动汽车充电站与换电站选址优化问题【含Matlab源码 1182期】
  13. MySQL table 添加_「primarykey」MySQL中为table添加primary key的两种方法 - seo实验室
  14. 2018年迎春杯复赛入围名单(五年级)
  15. Android获取超级管理员权限
  16. Java笔记 - 黑马程序员_04(枚举,异常,Collection,List,Set)
  17. android app 短信接收,Android创建简单发送和接收短信应用
  18. 群、环、域的概念总结
  19. 奇遇网以讨论电脑技术和互联网科技资源
  20. WriteFile 错误(GetLastError)返回998

热门文章

  1. PB 常见错误及含义
  2. 工欲利其事,常用软件使用感受交流分享
  3. linux安装及启动nsq流程
  4. linux 下搭建yolov3错误,yolov3---报段错误的可能原因及解决方法
  5. 20220316_Scanner、匿名对象、Random、ArrayList
  6. ZBrush: Alpha纹理生成雕花
  7. 论文写作课程内容总结
  8. nodejs express搭建服务器(爬虫知乎精华帖,个人学习用)六 在express中建立路由
  9. 解决MYSQL 8小时连接问题
  10. openwrt修改lan口地址失败_wr703n 刷openwrt 网口是lan口,怎样改成wan口?