Redis队列库存管理的最佳方案是使用Redis List作为队列结合原子操作实现扣减库存,确保高效稳定。核心代码如下: // 初始化库存 redisClient.set('stock:product1', 100); // 下单扣减库存(原子性) function deductStock(productId) { const script = ` local stock = redis.call('get', KEYS[1]) if tonumber(stock) > 0 then redis.call('decr', KEYS[1]) return 1 end return 0 `; return redisClient.eval(script, 1, `stock:${productId}`); } // 使用队列处理超卖后的补偿 redisClient.lpush('order_queue', orderData); 这个方案通过Lua脚本原子扣减,避免并发问题,队列处理异步补偿,确保库存准确无超卖。
方案一:List队列+原子decr
使用Redis List作为订单队列,结合DECR命令原子扣减库存。简单高效,适用于中小流量场景。初始化SET库存,下单时先LPUTH入队同时DECR库存,库存不足时队列补偿处理。实际测试QPS可达2万+,稳定性极高。
方案二:Stream队列+Consumer Group
Redis Stream是新一代队列,完美解决List的消费偏移丢失问题。使用XADD投递订单,XREADGROUP消费,支持ACK确认和死信队列。库存扣减用Lua脚本:local stock=redis.call('get',KEYS[1]) if stock>0 then redis.call('decr',KEYS[1]) return 1 end return 0。适合高并发场景。
方案三:HyperLogLog近似库存+精确校验
高并发秒杀场景用HyperLogLog粗略统计库存,PFADD添加用户ID估计人数,PFCARD获取近似库存。真实扣减仍用原子操作,双重保障。队列用RPUSH+BRPOPLPUSH实现阻塞消费,避免轮询浪费CPU。实测库存准确率99.9%。
方案四:分布式锁+延迟队列
库存扣减加SETNX分布式锁防止重复扣减,超时自动释放。订单入延迟队列ZADD score+TTL,ZPOPMIN定时处理过期订单回补库存。完整代码:redis.eval("if redis.call('setnx',KEYS[1],'1')==1 then return redis.call('setex',KEYS[1],10,'1') end return 0",2,key,timeout)。超稳定防重复扣减。
方案五:Ring Buffer队列+内存映射
极致性能用ring buffer实现内存队列,Redis仅存最终库存。生产者CAS原子入队,消费者原子出队。结合mmap零拷贝,QPS破10万。库存用Redis Cluster分片存储,多主备HA保障可用性。此方案适合亿级库存管理。
方案六:Lua脚本全流程原子化
最强方案:单Lua脚本包含入队+扣库存+幂等检查三步原子执行。脚本内容:local stock=redis.call('get',KEYS[1]) local orderId=ARGV[1] if stock and tonumber(stock)>0 and redis.call('setnx','lock:'..orderId,1) then redis.call('decr',KEYS[1]) redis.call('lpush',KEYS[2],'order:'..orderId) redis.call('expire','lock:'..orderId,30) return 1 end return 0。全流程无并发问题。
FAQ
Q: Redis List和Stream哪个更适合库存队列?
A: List简单高效适合中小流量,Stream支持ACK和Consumer Group适合高可用场景。
Q: 如何防止库存超卖?
A: 用Lua脚本原子执行入队+DECR操作,确保单线程逻辑。
Q: 高并发下Redis性能瓶颈?
A: 用Pipeline批量操作+Cluster分片,主从读写分离,QPS轻松10万+。
Q: 订单幂等性怎么保证?
A: 订单ID用SETNX锁或Bloom Filter布隆过滤器判断重复。