java幂等性的解决方案
一、幂等性概念
在编程中.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“getUsername()和setTrue()”函数就是一个幂等函数. 更复杂的操作幂等保证是利用唯一交易号(流水号)实现.
我的理解:幂等就是一个操作,不论执行多少次,产生的效果和返回的结果都是一样的。
二、幂等性场景
1、查询操作:查询一次和查询多次,在数据不变的情况下,查询结果是一样的。select是天然的幂等操作;
2、删除操作:删除操作也是幂等的,删除一次和多次删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个) ;
3、唯一索引:防止新增脏数据。比如:支付宝的资金账户,支付宝也有用户账户,每个用户只能有一个资金账户,怎么防止给用户创建资金账户多个,那么给资金账户表中的用户ID加唯一索引,所以一个用户新增成功一个资金账户记录。要点:唯一索引或唯一组合索引来防止新增数据存在脏数据(当表存在唯一索引,并发时新增报错时,再查询一次就可以了,数据应该已经存在了,返回结果即可);
4、token机制:防止页面重复提交。
原理上通过session token来实现的(也可以通过redis来实现)。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。
下次客户端提交请求时,Token会随着表单一起提交到服务器端。
服务器端第一次验证相同过后,会将session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变了。
5、悲观锁
获取数据的时候加锁获取。select * from table_xxx where id='xxx' for update; 注意:id字段一定是主键或者唯一索引,不然是锁表,会死人的;悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用;
6、乐观锁——乐观锁只是在更新数据那一刻锁表,其他时间不锁表,所以相对于悲观锁,效率更高。乐观锁的实现方式多种多样可以通过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,这个两个字段在提供方系统里面做联合唯一索引,这样当第三方调用时,先在本方系统里面查询一下,是否已经处理过,返回相应处理结果;没有处理过,进行相应处理,返回结果。注意,为了幂等友好,一定要先查询一下,是否处理过该笔业务,不查询直接插入业务系统,会报错,但实际已经处理了。
三、总结
幂等与你是不是分布式高并发还有JavaEE都没有关系。关键是你的操作是不是幂等的。一个幂等的操作典型如:把编号为5的记录的A字段设置为0这种操作不管执行多少次都是幂等的。一个非幂等的操作典型如:把编号为5的记录的A字段增加1这种操作显然就不是幂等的。要做到幂等性,从接口设计上来说不设计任何非幂等的操作即可。譬如说需求是:当用户点击赞同时,将答案的赞同数量+1。改为:当用户点击赞同时,确保答案赞同表中存在一条记录,用户、答案。赞同数量由答案赞同表统计出来。在设计系统时,是首要考虑的问题,尤其是在像支付宝,银行,互联网金融公司等涉及的都是钱的系统,既要高效,数据也要准确,所以不能出现多扣款,多打款等问题,这样会很难处理,用户体验也不好。
java幂等性的解决方案的更多相关文章
- java 幂等性(转)
(转自)http://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html 理解HTTP幂等性 基于HTTP协议的Web ...
- Java Scoket之java.io.EOFException解决方案
Java Scoket之java.io.EOFException解决方案 Socket接收数据的时候,常常会抛出java.io.EOFException异常,也没有明确的原因和提示,在网上搜搜,很 ...
- Java 图片处理解决方案:ImageMagick 快速入门
一.ImageMagick介绍 ImageMagick是一个免费的创建.编辑.合成图片的软件,可以实现图片切割.颜色替换.图片缩略图.图片水印等各种效果.ImageMagick是免费开源软件,支持大多 ...
- Java 图片处理解决方案:ImageMagick 快速入门教程
文章首发于[博客园-陈树义],点击跳转到原文Java 图片处理解决方案:ImageMagick 快速入门教程. ImageMagick介绍 ImageMagick是一个免费的创建.编辑.合成图片的软件 ...
- Java中文乱码解决方案
Java中文乱码解决方案 1.中文乱码解决方案,确保每个文件的默认编码是UTF-8 加入 URIEncoding="UTF-8" 代码中的设置 1>在se ...
- Atitit.java jar hell解决方案-----Djava.ext.dirs in ide envi..
Atitit.java jar hell解决方案-----Djava.ext.dirs in ide envi.. Atitit.java class flect solu jar hell use ...
- java 乱码问题解决方案
java 乱码问题解决方案 一.tomcat: <Connector port="8080" maxThreads="150&qu ...
- java compiler level does not match the version of the installed java project facet 解决方案
项目出现 java compiler level does not match the version of the installed java project facet 错误,一般是项目移植出现 ...
- idea生成JAVADOC 报java.lang.IllegalArgumentException解决方案[终极]
idea生成javadoc文档,总是会报 java.lang.IllegalArgumentException at sun.net.www.ParseUtil.decode(ParseUt ...
随机推荐
- ES6+javaScript原型
Symbol 属性私有化,数据保护 let _gender = Symbol('gender') function Person(name, gender) { this.name = name; t ...
- python简单名片管理系统
- Oracle Loop
1. LOOP - END LOOP - EXIT declare v_rlt ):; begin v_rlt:; loop dbms_output.put_line('loop'||v_rlt); ...
- jmeter使用Beanshell预处理器从指定列表中获取随机值
变量mynation从列表{"china", "US", "UK"}中随机取值 String[] nation = new String[] ...
- 块级元素或者行内元素在设置float属性之后是否改变元素的性质?
块级元素使用float属性后,将其属性变成inline-block,不能改变其块级元素的性质,只是能有块级元素的特性,不独占一行,宽度不会占满父元素,和行内元素排列成一行 行内元素使用float属性后 ...
- SW加载标准库时出现failed to create Toolboxlibrary object怎么办?
友情提示:Windows+r打开 输入smd 注意操作前要关闭solidworks, 重新打开软件. 下面就可以找到很多标准件了.
- 多轴APM飞控调参
调参步骤: 遥控器,电动机和电调对应的APM飞控连线——遥控器校准——电调行程校准——加速度计校准——磁罗盘校准——故障保护设定(遥控器和飞控)——飞行模式设定并调整——自动调参设定选项 APM飞控调 ...
- npm install出现"Unexpected end of JSON input while parsing near"
打开命令行输入 npm cache clean --force 重新npm i,即可解决报错
- [USACO18DEC]Cowpatibility
Description: Farmer John 的 \(N\) 头奶牛(\(2\le N\le 5\times 10^4\))各自列举了她们最喜欢的五种冰激凌口味的清单.为使这个清单更加精炼,每种可 ...
- python流程控制之if、 while和for 循环
1.if 语句 语法1 if 条件:# 代码1# ... # cls='human'# sex='female'# age=18## if cls == 'human' and sex == 'fem ...