库存管理是电商和零售系统的核心问题之一,超卖(卖出的数量超过实际库存)和少卖(实际有库存但未能卖出)都会带来严重问题。以下是几种有效的防止策略:
1. 数据库层面的解决方案
乐观锁机制
UPDATE inventory SET stock = stock - #{quantity}, version = version + 1
WHERE product_id = #{productId} AND version = #{version} AND stock >= #{quantity}
悲观锁机制
SELECT * FROM inventory WHERE product_id = #{productId} FOR UPDATE;
-- 然后执行扣减
2. 分布式锁方案
使用Redis或Zookeeper实现分布式锁,确保同一时间只有一个请求能处理特定商品的库存:
// 伪代码示例
try {
boolean locked = redisLock.tryLock(productId, timeout);
if (locked) {
// 检查并扣减库存
}
} finally {
redisLock.unlock(productId);
}
3. 预扣库存方案(TCC)
- 下单时先预扣库存(冻结库存)
- 支付成功后再实际扣减
- 支付超时后释放预扣库存
4. 消息队列削峰
使用消息队列缓冲高并发请求:
1. 接收订单请求后立即返回"处理中"
2. 将请求放入消息队列
3. 后台服务顺序处理队列中的请求
5. 库存分段策略
将库存拆分为多个段(如1000库存分为10个100),不同段使用不同的锁,提高并发能力。
6. 缓存+异步方案
- 使用Redis缓存库存数量
- 先扣减Redis中的库存(LUA脚本实现库存扣减)
- 异步同步到数据库
- 定期对账确保一致性
-- KEYS[1]: 库存key
-- ARGV[1]: 要扣减的数量
-- 返回值: 1-成功 0-失败
local stock = tonumber(redis.call('GET', KEYS[1]))
if stock and stock >= tonumber(ARGV[1]) then
redis.call('DECRBY', KEYS[1], ARGV[1])
return 1
else
return 0
end
7. 防止少卖的注意事项
- 确保库存释放机制完善(取消订单、支付超时等场景)
- 实现有效的库存预警机制
- 定期库存盘点和对账
- 处理好分布式事务,确保扣减和订单状态的一致性
选择哪种方案取决于系统的规模、并发量和对一致性的要求。高并发场景通常需要组合多种策略来实现最佳效果。