本文介绍的幂等的概念,以及幂等的场景和解决办法。
参考
幂等
幂等就是调用多次接口只会产生相同的结果,不会改变业务状态。
幂等的场景通常有:
- RestAPI:包括我们的对外HTTP接口,可能会出现前端表单重复提交的情况。RPC接口,可能出现超时重试的机制。
- MQ:消息中间件保证消息的可靠性的同时,也会有消息重复消费的可能。
Token
开放一个获取Token的接口,前端获取token,后面的请求带上token,后端存入Redis中,设上有效时间。后端收到请求后,把Redis中的token删除,这样后面的请求发过来时,查询token为空,就直接返回。
Redis
采用分布式锁,设计一个唯一id,使用AOP加自定义注解环绕指定接口。超时时间的设计
RestAPI场景
唯一id可以有多种设计方法,一是以访问的路径名加参数的md5值为id。另一种是采用SpEL通过一些方法生成指定的id。
MQ场景
MQ场景是在消费方做幂等,通常使用SpEL方法,通过SpEL方法可以获取到收到的message,获取其中的唯一键。同时在Redis维护消息的消费状态,如果在发现重复请求并且还处于消费状态,那么就走异常处理。
乐观锁
在表中加入一个version
字段,每次更新时先获取version,在后面的更新操作中加入where version=?
。判断影响的行数,如果影响0行,那么直接返回成功,因为已经有人改过了。
唯一索引
建立一张去重表,以原表中的多个字段的和作为唯一索引,如用户名+手机号,当多个请求同时进入时,只会有一个请求在去重表中插入,注意去重表和原表要在同一个事务中,不然在原表中发生异常,去重表也无法回滚。
状态机
对于表中有状态的字段,如订单的创建,付款,退款等等,它是有顺序的,可以在更新时加上where status=1
来保证幂等性。