
介绍
幂等性就是同一个操做执行屡次,产生的效果同样。如http的get请求,数据库的select请求就是幂等的前端
在分布式系统中,保证接口的幂等性很是重要,如提交订单,扣款等接口都要保证幂等性,否则会形成重复建立订单,重复扣款,那么如何保证接口的幂等性呢?mysql
前端保证幂等性的方法
按钮只能点击一次web
用户点击按钮后将按钮置灰,或者显示loading状态redis
RPG模式sql
即Post-Redirect-Get,当客户提交表单后,去执行一个客户端的重定向,转到提交成功页面。避免用户按F5刷新致使的重复提交,也能消除按浏览器后退键致使的重复提交问题。目前绝大多数公司都是这样作的,好比淘宝,京东等数据库
后端保证幂等性的方法
使用惟一索引后端
对业务惟一的字段加上惟一索引,这样当数据重复时,插入数据库会抛异常浏览器
状态机幂等微信
若是业务上须要修改订单状态,例如订单状态有待支付,支付中,支付成功,支付失败。设计时最好只支持状态的单向改变。这样在更新的时候就能够加上条件,屡次调用也只会执行一次。例如想把订单状态更新为支持成功,则以前的状态必须为支付中并发
update table_name set status = 支付成功 where status = 支付中
乐观锁实现幂等
-
查询数据得到版本号 -
经过版本号去更新,版本号匹配则更新,版本号不匹配则不更新
-- 假如查询出的version为1
select version from table_name where userid = 10;
-- 给用户的帐户加10
update table_name set money = money -10, version = version + 1 where userid = 10 and version = 1
也能够经过条件来实现乐观锁,如库存不能超卖,数量不能小于0
update table_name set num = num - 10 where num - 10 >= 0
防重表
增长一个防重表,业务惟一的id做为惟一索引,如订单号,当想针对订单作一系列操做时,能够向防重表中插入一条记录,插入成功,执行后续操做,插入失败,则不执行后续操做。本质上能够当作是基于MySQL实现的分布式锁。根据业务场景决定执行成功后,是否删除防重表中对应的数据
分布式锁实现幂等
执行方法时,先根据业务惟一的id获取分布式锁,获取成功,则执行,失败则不执行。分布式锁能够基于redis,zookeeper,mysql来实现,分布式锁的细节就不介绍了
select+insert
先查询一下有没有符合要求的数据,若是没有再执行插入。没有并发的系统中能够保证幂等性,高并发下不要用这种方法,也会形成数据的重复插入。我通常作消息幂等的时候就是先select,有数据直接返回,没有数据加分布式锁进行insert操做
全局惟一号实现幂等
经过source(来源)+ seq(序列号)来判断请求是否重复,重复则直接返回请求重复提交,不然执行。如当多个三方系统调用服务的时候,就能够采用这种方式

欢迎关注

有帮助?点赞!转发!
本文分享自微信公众号 - Java识堂(erlieStar)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。