为什么要做幂等?
幂等就是一个操作,不论执行多少次,产生的效果和返回的结果都是一样的。
例如
1、 前端重复提交选中的数据,应该后台只产生对应这个数据的一个反应结果。
2、 我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱;
3、 发送消息,也应该只发一次,同样的短信发给用户,用户会哭的;
4、 创建业务订单,一次业务请求只能创建一个,创建多个就会出大问题。
如何保证幂等?
查询
查询天然幂等。添加
通过业务唯一键保证:
当插入时抛出DuplicateKeyException异常时表示已经插入成功
或考虑INSERT IGNORE INTO和REPLACE INTO删除
删除也是天然的幂等,删除一次和多次删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个)MVCC方案
多版本并发控制,update with condition
,更新带条件,这也是在系统设计的时候,合理的选择乐观锁,通过version或者其他条件,来做乐观锁,这样保证更新及时在并发的情况下,也不会有太大的问题。例如update table_xxx set name=#name#,version=version+1 where version=#version#
,或者是update table_xxx set quality=quality-#subQuality# where quality-#subQuality# >= 0
悲观锁
获取数据的时候加锁:select * from table_xxx where id='xxx' for update;
注意:
- id字段一定是主键或者唯一索引,不然是锁表,会死人的
- 悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用
单独的去重表
分布式锁
状态机幂等
API层token机制
由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交。
参考
https://www.jianshu.com/p/37537fdb170f
https://www.jianshu.com/p/00cf7d7abbf7
https://www.jianshu.com/p/972ce0c98ce2
http://chuanwang66.iteye.com/blog/1328563
http://blog.720ui.com/2017/server_statemachine/
https://www.jianshu.com/p/475589f5cd7b
http://www.daydaytc.com/mysql/42.html
https://www.jianshu.com/p/e4fb0325b252