解释
接口幂等性就是:用户对于 同一操作 发起的 一次请求 或者 多次请求 的结果是一致的,不会因为多次点击而产生了副作用。
如果 多次点击,产生了副作用,说明 没有保证接口幂等性
例子
支付场景,用户购买了商品支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,流水记录也变成了两条,此时就没有保证接口的幂等性
哪些情况下需要保证接口幂等性
- 用户多次点击提交按钮
如:添加学生信息时,由于网络延迟,没反应,就多次点击提交,结果该学生的信息在系统中出现好几条记录 - 用户页面回退再次提交(页面重复提交)
- 微服务之间互相调用,由于网络问题,导致请求失败,ribbon、feign触发重试机制
- 。。。。。
增删改查 哪些操作需要幂等性
增加操作
需要 手动实现幂等性
删除操作
删除一次和多次删除都是把数据删除。
注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个
在不考虑返回结果的情况下,删除操作天然具备幂等性,不需要手动实现
修改操作
类似修改密码、昵称的修改操作,天然具备幂等性
让某字段增加1,这种操作就需要手动实现幂等性,否则 该字段的值会增加多次
查询操作
查询对于结果是不会有改变的,查询一次和查询多次,在数据不变的情况下,查询结果是一样的。查询操作天然具备幂等性
http协议
post
在HTTP规范中对POST和PUT是这样定义的:
The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line …… If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.
两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性
put
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
PUT方法具有幂等性
常见解决方案
唯一索引 — 防止新增脏数据
token机制 — 防止页面重复提交
悲观锁 — 获取数据的时候加锁(锁表或锁行)
乐观锁 — 基于版本号version实现, 在更新数据那一刻校验数据
分布式锁 — redis(jedis、redisson)或zookeeper实现
状态机 — 状态变更, 更新数据时判断状态
token机制
分以下2种:
集群环境:采用 token + redis(redis 单线程的,处理需要排队)
单 JVM 环境:采用 token + redis 或 token + jvm 内存
token+redis 处理流程:
服务端提供发送 token 的接口,在需要幂等问题的业务执行前,先去获取token,服务器会把token保存在redis 或 jvm 内存(原子性),token 具有 有效时间
调用业务接口时,把token携带过去,一般放在请求的头部.
服务器判断 token 是否存在 redis中,存在表示第一次请求,然后删除token,继续执行业务
如果判断token不存在redis中,即表示为重复操作,直接返回重复标记给客户端,保证业务代码不被重复执行.
token 特点:要申请,一次有效性,可以限流
缺点
先删除token还是后删除token;
- 先删除可能导致,业务还没执行就闪断,后面的请求任然无法执行
- 后删除也可能出现业务成功后再删除前闪断.
token的获取,比较和删除必须是原子的(lua脚本实现)
如果操作不原子,高并发下可能多个业务同时判断成功,都执行
具体实现 点击
https://blog.csdn.net/weixin_44634197/article/details/108647258