接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条,这就没有保证接口的幂等性。
【a】数据库唯一约束
插入数据,应该按照唯一索引进行插入,比如订单号,相同的订单号就不可能有两条记录插入,我们在数据库层面防止重复。
这个机制是利用了数据库的主键唯一索引的特性,解决了在插入场景时的幂等问题。
【b】redis set防重
很多数据需要处理,只能被处理一次,比如我们可以计算数据的MD5将其放入redis的set数据结构,每次处理数据,先看这个MD5是否已经存在,如果已经存在就不处理。
【c】防重数据表
使用订单号orderNo作为去重表的唯一索引,把唯一索引插入去重表,再进行业务操作,且他们在同一事务操作中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。这里要注意的是,去重表和业务表应该在同一个数据库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的数据回滚。这个很好的保证了数据的一致性。
【d】数据库锁
数据库常见的锁也就是乐观锁和悲观锁。
【e】业务层分布式锁
如果多个线程可能在同一时间处理相同的数据,比如多个线程在同一时刻都拿到了相同的数据处理,我们就可以加分布式锁,锁定此数据,处理完成后释放锁。获取到锁的必须先判断这个数据是否被处理过。
【f】Token机制
每次接口请求的时候带上token令牌,服务器第一次处理的时候去校验token,并且这个token只能用一次,如果用户使用相同的令牌请求二次,那么第二次就不处理,直接返回。

大体的流程如下:
1、服务端提供了发送Token的接口,在执行业务前,先去获取Token,服务器会把Token保存到redis中;
2、然后调用业务接口请求时,把token携带过去,一般作为请求参数或者请求头中传递;
3、服务器判断token是否存在redis中,存在表示第一次请求,然后删除token,继续执行业务;
4、服务器如果短时间内重复提交这个接口,因为两次请求token是一样的,所以第二次请求的时候,服务器校验token时,redis中已经没有了刚刚被第一次删掉的token,就表示是重复操作,所以第二次请求会校验失败,不作处理,这样就保证了业务代码,不被重复执行;