当前位置:网站首页>如何防止重复下单?
如何防止重复下单?
2022-08-04 15:29:00 【InfoQ】
用户下单流程

- 浏览商品:用户查看商品详情
- 加购/结算:用户可以选择直接购买商品,也可以先加入购物车,用户购买的这一步就是结算
- 确认下单:结算完成,就进入了下单页面,
提交订单,这一步就会生成一个订单,然后进入付款页面
为什么会重复下单
- 用户重复提交
- 网络原因导致的超时重试

如何防止重复下单

requestId利用数据库实现幂等
t_orderrequestId
PlaceOrderResVO placeOrder(PlaceOrderReqVO reqVO) {
try {
//下单业务逻辑
……
//生成订单号
String oid=generateOid();
……
//订单落库
Order order = orderMapper.saveOrder(orderDO);
//响应订单
resVO.setOid(order.getOid());
return resVO;
} catch(UniqueKeyViolationException e) {
// 发生了重复异常
// 根据请求号获取订单
Order order = getOrderByRequestId(reqVO.getRequestId());
resVO.setOid(order.getOid());
return resVO;
} catch (Exception e) {
}
}
利用Redis防重
- 就是以
requestId为维度,进行加锁,如果获取锁失败,就抛一个自定义的重复下单异常。
- 如果获取到锁,先check一下,是否已经下单,为了提高性能,下单完成后,也把下单的结果放在Redis缓存里。

public PlaceOrderResVO placeOrder(PlaceOrderReqVO reqVO) {
//加锁
RLock orderLock = redissonClient.getLock(RedisConstant.PLACE_ORDER_LOCK_KEY + reqVO.getRequestId());
//获取锁失败,抛出重复下单异常
if(orderLock.isExistes){
throw new OrderRepeatException();
}
// 加锁
orderLock.lock();
try {
//检查是否已经下单
RBucket<PlaceOrderResVO> orderCache = redissonClient.getBucket(RedisConstant.PLACE_ORDER_LOCK_KEY+reqVO.getRequestId());
if(orderCache.isExistes){
return orderCache.get();
}
//下单业务逻辑
……
//落库
//订单落库
Order order = orderMapper.saveOrder(orderDO);
……
//缓存结果
orderCache.put(resVO);
return resVO;
}
} catch (Exception e) {
//……
} finally {
orderLock.unlock();
}
return resVO;
}
- 为什么获取不到锁的时候要抛异常呢?
边栏推荐
- 直播回放含 PPT 下载|基于 Flink & DeepRec 构建 Online Deep Learning
- 宣传海报
- HarePoint Analytics for SharePoint Online
- IP第十六天笔记
- 从-99打造Sentinel高可用集群限流中间件
- 《2022 年上半年全球独角兽企业发展研究报告》发布——DEMO WORLD世界创新峰会圆满落幕
- remote: Check Access Error, please check your access right or username and password!fatal: Authenti
- 直播系统开发——直播间架构的设计及难点分析
- 2022年7月国产数据库大事记-墨天轮
- PTA 6-2 多项式求值
猜你喜欢

leetcode: 250. Count subtrees of equal value

明明加了唯一索引,为什么还是产生重复数据?

postman “header“:{“retCode“:“999999“

Why, when you added a unique index or create duplicate data?

Redis-哨兵模式

2022 Hangzhou Electric Multi-School 4

NUS颜水成等发布首篇《深度长尾学习》综述

Pisanix v0.2.0 发布|新增动态读写分离支持

关于pnpm包管理器的版本问题

(2022杭电多校五)C - Slipper (dijkstra+虚拟结点)
随机推荐
Go 言 Go 语,一文看懂 Go 语言文件操作
Why, when you added a unique index or create duplicate data?
你一定从未看过如此通俗易懂的YOLO系列(从v1到v5)模型解读
Byte、Short、Integer、Long内部缓存类的对比与源码分析
《电磁兼容防护EMC》学习笔记
Next -20- 使用自定义样式 (custom style)
技术分享| 小程序实现音视频通话
从-99打造Sentinel高可用集群限流中间件
成员变量与局部变量的区别有哪些
苏秋贵:揭秘绿联科技用5年时间从0做到6亿,如何一枝独秀?
剑指Offer 63.股票的最大利润
AIX7.1安装Oracle11g补丁33829709(PSU+OJVM)
C# BBcode 转 Markdown
附加:自定义注解(参数校验注解);(写的不好,别看…)
PHP 图片转PDF
使用百度EasyDL实现森林火灾预警识别
实战:10 种实现延迟任务的方法,附代码!
宣传海报
leetcode: 250. Count subtrees of equal value
FTP协议抓包-工具wireshark与filezilla