概念
幂等性是指:多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致。
也就是保证一条请求只被执行一次,不会因为网络等问题的影响被执行多次。
出现原因
- 前端误操作连续多次点击;
- 网络原因接口超时导致重试;
- 消息异步消费时没有确认进程就意外挂起,导致消息被多次消费;
常见解决方案
使用token机制保证操作唯一性
流程如下:
- 客户端从服务端请求token,服务端返回token并存入redis等;
- 客户端做业务请求时携带token,服务端判断token是否存在,若存在:处理请求,删除token;
- 若不存在,代表重复请求,直接返回,不处理;
基于mysql的唯一索引实现
这个流程比较简单,把请求的某些信息(必须具有唯一性)存入MySQL的一个字段中,给该字段添加唯一索引;后续如果插入失败则表示该请求是重复请求,不用处理;
这个方法存在问题,表数据会累积以及信息如何设置唯一性;同时数据库io存在性能问题,不推荐;
基于redis的setnx来实现
跟第二种方法思路是一样的,setnx仅在key不存在时设置成功返回1,如果key已经存在则返回0,相比第二种好处是redis速度快,不会对请求本身的速度造成很大影响。
总结
其实幂等性的设计和高qps的电商系统里某些设计思路是一样的,库存/秒杀等功能需要保证(商品数)等信息全局唯一,操作线性的时候,就会用到类似的操作。思路也差不太多;电商系统里的分布式锁也会用到redis的setnx去实现,思路都是差不多的。