什么是幂等性
幂等性简单的说就是相同条件下,一次请求和多次重复的请求,接口的执行结果是相同的。
什么情况下会出现幂等性问题呢?
- 前端重复提交表单:如用户在提交表单的时候,由于网络波动没有及时给用户做出提交成功响应,导致用户认为没有提交成功,一直点击提交按钮,此时就会发生表单重复提交。
- 接口超时重试:很多远程接口调用为了防止由于网络抖动导致的请求失败,都会引入重试机制,如feign的重试机制,导致一个请求发出多次。
- 消息重复消费:在使用消息中间件时,一个消息可能会被重复发送,此时就会发生重复消费。
幂等性解决方案
方案一:数据库主键唯一性约束
利用数据库主键唯一性约束的特性,在插入数据的时候,如果主键已经存在,就会插入失败,从而保证幂等性。
方案二:数据库乐观锁实现幂等性
一般适合更新操作,需要我们在数据库中多添加一个版本字段,在每次修改数据的时候,先进行版本号的比对,版本号比对成功才会进行更新操作,同时版本号也需进行修改。(相当于每修改一次数据,就升级一次版本)
update table set price = price + 100,version=version+1 where id = 1 ADN version = 1
方案三:上游服务传递全局唯一id实现幂等性
在调用远程接口时,传递一个唯一id,远程服务拿着这个全局id和自己的认证ID作为redis的键,去redis中查询,进行判断:
- 存在,说明之前处理过,直接返回重复请求的错误信息;
- 不存在,将用全局id和自己的认证ID作为redis的键,保存在redis中,然后处理业务;
方案四:token机制
-
常规token机制
以下订单为例:
- 用户在提交订单前先向服务器申请一个token(比如在生成订单信息返回一个token),服务器将这个token保存在redis中。
- 用户提交订单时,携带该token过去
- 服务器判断token在redis中是否存在,存在表明是第一次请求,然后删除token,继续执行业务
- 如果不存在,则表明是重复操作,直接返回重复操作提示给客户端,这样就保证了业务代码不会被重复执行。
-
非常规token机制
流程:
- 同样用户需要先到服务器中申请一个token,不同的是,服务器没有将token存入redis中
- 用户请求的时候携带上token,服务器使用redis的set NX,PX(NX代表只有key不存在时才设置成功,PX代表在过期时间后会自动释放)尝试将token保存到redis中
- 如果保存成功的话,说明是第一次请求,执行业务代码。如果保存失败,说明是重复请求,向用户提示重复请求。
幂等性总结: