01.接口幂等
订单重复创建的幂等性解决方法包括后端生成唯一订单号、前端生成唯一订单号以及业务逻辑唯一标识,如用户ID+商品ID。
通过数据库的唯一索引,防止重复插入订单。
消息重复消费问题可通过Redis生成唯一消息ID并记录消费状态,防止重复消费。
如果要求较高,还可使用持久化记录消息状态来避免过期引发的重复消费。
# 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来替代
上次更新: 2024/10/15 16:27:13