幂等性:对接口的多余重复调用的结果和单次调用的结果一致。
一、需要幂等性的场景
二、幂等性实现方案
核心思想:首先要根据业务判断什么是重复相同的请求,然后相同的请求都携带或生成一个唯一的识别码,这样在服务端就可以进行判别处理
1. 基于token机制实现
在允许一次独立的接口调用前先向服务端请求生成一个唯一token并存放在redis,当发起接口请求调用时携带上这个token,服务端进行校验,请求成功就删除这个token,后续的重复请求就无效了。
例如在防止订单重复提交时,除了在前端设置请求加载蒙版外,还可以在进入提交订单页面时先向服务端请求一个token,这样在同一个订单页面的重复点击请求就无效了。
对 redis 中是否存在 token 以及删除的代码逻辑建议用 Lua 脚本实现,保证原子性
2. 基于MySQL唯一索引实现
相同的请求对应同一个唯一字段值,比如将订单号作为唯一索引,那么相同的请求只有第一个能Insert成功,其它的由于唯一索引冲突都会阻塞等待记录的X锁释放,拿到锁后插入由于索引已经存在故插入失败。
3. 基于redis分布式锁+双重检查实现
使用请求的数据生成一个唯一code,然后检查这个请求有没有处理过,没有则针对这个code尝试在redis集群中获取分布式锁,加锁成功再开启事务操作,事务提交后再释放分布式锁。并且在操作前先检查该请求有没有处理过,没有才进行处理,否则直接结束事务。
和DCL单例思想类似
参考:
- https://zhuanlan.zhihu.com/p/345512692
- https://www.bilibili.com/video/BV1TX4y1z7Ax
- https://www.bilibili.com/video/BV1uv4y1S7tE