既然这么多场景需要考虑幂等,那我们如何设计幂等呢?
幂等意味着 一条请求的唯一性。不管是你哪个方案去设计幂等,都需要一个
全局唯一的ID,去标记这个请求是独一无二的。
唯一索引控制幂等,那唯一索引是唯一的数据库主键控制幂等,那主键是唯一的悲观锁的方式,底层标记还是全局唯一的ID全局的唯一性ID
uuid–redis自增–雪花算法等
过滤一下已经收到的请求,当然,请求一定要有一个全局唯一的ID标记哈。
然后,怎么判断请求是否之前收到过呢?把请求储存起来,收到请求时,先查下存储记录,记录存在就返回上次的结果,不存在就处理请求

有时候表中并非所有的场景都不允许产生重复的数据,只有某些特定场景
才不允许。这时候,直接在表中加唯一索引,显然是不太合适的。
针对这种情况,我们可以通过建防重表来解决问题。
该表可以只包含两个字段:id 和 唯一索引,唯一索引可以是多个字段比如:name、code 等组合起来的唯一标识,例如:susan_0001。
具体流程图如下

具体步骤:
mysql 防重表很多时候业务表是有状态的,比如订单表中有:1-下单、2-已支付、3-完成、4-撤销等状态。
如果这些状态的值是有规律的,按照业务节点正好是从小到大,我们就能通过它来保证接口的幂等性。
假如 id=123 的订单状态是已支付,现在要变成完成状态。
update `order` set status=3 where id=123 and status=2;
第一次请求时,该订单的状态是已支付,值 2,所以该 update 语句可以正常更新数据,sql 执行结果的影响行数是 1,订单状态变成3
后面有相同的请求过来,再执行相同的 sql 时,由于订单状态变成了 3,再用 status=2 作为条件,无法查询出需要更新的数据,所以最终 sql 执行
结果的影响行数是 0,即 不会真正的更新数据。但为了保证接口幂等性,
影响行数是 0 时,接口也可以直接返回成功。
具体流程图如下:

具体步骤:
仅限于要更新的表有状态字段,并且刚好要更新状态字段的这种特殊情况,并非所有场景都适用。防止重复下单(redis+数据库唯一索引requestId实现幂等)
springboot + redis + 注解 + 拦截器用Token 实现接口幂等性
使用 token 的方案。该方案跟之前的所有方案都有点不一样,需要两次请求才能完成一次业务操作。

具体步骤:
针对幂等设计的如果是防重设计,流程图要改改

需要特别注意的是:
token 必须是全局唯一的
上一篇:想念一个人,用诗句表达出来
下一篇:抗日战争各个阶段及其标志、口号