02.接口幂等
# 01.订单重复创建
# 0、幂等
- 接口幂等是什么
- 以相同的参数,对一个接口进行多次调用,所产生的结果和一次调用是完全相同的
- 重复提交的两种原因
- 一种是由于用户在短时间内多次点击下单按钮,或浏览器刷新按钮导致
- 另一种则是由于Nginx或类似于SpringCloud Gateway的网关层,进行超时重试造成的
# 1、后端唯一订单号
- 后端新增一个接口,用于预生成一个“全局唯一订单号”
- 进入创建订单页面时,前端请求该接口,获取该订单号。
- 在提交订单时,请求参数里要带上这个预生成的“全局唯一订单号”
- 利用数据库的唯一索引特性,在插入订单记录时,如果该“全局唯一的订单号”重复,记录会插入失败。
优点
:彻底解决了重复下单的问题;
缺点
:方案复杂,前后端都有开发工作量,还要新增接口,新增字段。
# 2、前端唯一订单号
- 用户进入下页面时,前端程序自己生成一个“全局唯一订单号”。
- 利用数据库的唯一索引特性,在插入订单记录时,如果该“全局唯一的订单号”重复,记录会插入失败
优点
:彻底解决了重复下单的问题,且技术方案做了一定简化;
缺点
:前后端仍然都有开发工作量,且需要新增字段;
# 3、从订单业务的本质入手
- 可以用 ”用户ID + 分隔符 + 商品ID“ 作为唯一标识
- 让持有相同标识的请求在短时间内不能重复下单
优点
:彻底解决了重复下单的问题,且在技术方案上,不需要前端参与,不需要添加接口,不需要添加字段
缺点
:综合比较而言,暂无明显缺点,如果硬要找缺点的话,可能强依赖于Redis勉强可以算上吧
# 02.消息重复消费
# 1、问题说明
- 在分布式系统中,消息队列扮演着重要的角色,它能够实现系统间的解耦和异步通信。
- 然而,由于网络、硬件和服务故障等原因,消息在传递过程中可能会发生重复消费的情况。
- 这会导致系统中的数据出现不一致性,并产生预期之外的副作用。
# 2、redis解决方案
- 生成者在发送每一条消息之前,生成一个唯一的消息ID
- 使用redis的hash结构存储
- key: 消息唯一ID
- value:
- 0:有其他任务再消费(可以直接忽略该消息)
- 1:消息已经被消费(这个时候可以手动ack确认)
- 处理完消息后,将缓存中这个消息的值修改为1,最后手动ack确认消息成功消费
- 在存储消息ID时,可以设置过期时间,以便自动清理不需要的数据
- 这种方案理论上依然会存在重复消费问题
- 一般使用redis缓存是会设置消息ID的过期时间,如果过期后依然会出现重复消费问题
- 如果系统有极强的要求,可能还需要配合持久化消息(比如通过mysql来记录消息ID+状态变更)
注:redis缓存方案性能比较好,如果有极高要求的系统,可以使用持久化消息ID来替代
编辑 (opens new window)
上次更新: 2024/3/13 15:35:10