实战商品订单秒杀设计实现
前言
在高并发秒杀、抢购等场景下,订单系统极易出现"超卖"问题,即实际售出的商品数量超过库存。本文将详细介绍超卖的成因、常见解决方案,重点讲解如何通过Redis实现高效、可靠的防超卖机制,并给出实用代码和优化建议。
1. 超卖问题背景
1.1 什么是超卖
超卖指的是在并发环境下,多个用户同时下单,导致实际售出商品数量超过库存。例如,库存只有10件,但最终卖出了12件。
1.2 超卖产生的原因
- 多线程/多进程并发下,库存判断和扣减不是原子操作
- 数据库操作未加锁或锁粒度过大,影响性能
- 分布式部署下,节点间状态不一致
2. 常见防超卖方案
- 数据库加锁:如悲观锁(for update)、乐观锁(版本号/时间戳)
- 队列削峰:下单请求入队,单线程消费
- 缓存预扣减:用Redis等缓存中间件做库存扣减
其中,基于Redis的方案因高性能、易扩展、支持分布式而被广泛采用。
3. 基于Redis的防超卖原理
3.1 Redis的优势
- 单线程模型,天然支持原子操作
- 支持高并发、低延迟
- 提供分布式锁、Lua脚本等机制
3.2 实现思路
- 库存预先写入Redis
- 用户下单时,先在Redis中原子扣减库存
- 扣减成功再写入订单数据库
- 扣减失败(库存不足)则下单失败
4. Redis防超卖实现方式
4.1 基础实现:decr原子扣减
// 初始化库存
redisTemplate.opsForValue().set("product_stock:1001", 10);
// 下单接口伪代码
public String placeOrder(Long productId) {
Long stock = redisTemplate.opsForValue().decrement("product_stock:" + productId);
if (stock < 0) {
// 库存不足,回滚
redisTemplate.opsForValue().increment("product_stock:" + productId