如何利用Python和Redis队列结合Lua脚本高效处理大并发秒杀活动中的库存扣减?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1111个文字,预计阅读时间需要5分钟。
Redis 的常规读写命令间不存在锁机制,因此两个请求同时执行 GET 到库存储为 1,随后都会执行 DECR 或 SET,结果变为 -1。这并非 Redis 慢,而是逻辑漏洞。
必须把“读库存→判断→扣减→写回”整个流程塞进一个原子执行单元里。Lua 脚本是唯一靠谱的选择——它在 Redis 服务端一次性解析、执行,中间不会被其他命令打断。
-
EVAL是入口,脚本内容和 key 参数要严格对应,key 必须显式传入,不能硬编码在 Lua 里 - 脚本里用
redis.call("GET", KEYS[1])读,用redis.call("DECR", KEYS[1])扣,别用INCRBY -1——语义不清,容易看错 - 返回值建议用
if stock > 0 then return 1 else return 0 end,让客户端靠数字判断成败,别返回字符串
用 LPUSH + BRPOP 做队列,但别直接丢订单进 Redis 队列
秒杀请求量大时,如果每个请求都 LPUSH 一条订单数据到 Redis 队列,Redis 内存会暴涨,还可能因单条 value 过大(比如含用户完整信息)拖慢响应。这不是队列不行,是压根没做前置过滤。
真正该进队列的,只是最小必要信息:商品 ID、用户 ID、时间戳。其他字段(收货地址、支付方式)等消费端从下游 DB 补全。
本文共计1111个文字,预计阅读时间需要5分钟。
Redis 的常规读写命令间不存在锁机制,因此两个请求同时执行 GET 到库存储为 1,随后都会执行 DECR 或 SET,结果变为 -1。这并非 Redis 慢,而是逻辑漏洞。
必须把“读库存→判断→扣减→写回”整个流程塞进一个原子执行单元里。Lua 脚本是唯一靠谱的选择——它在 Redis 服务端一次性解析、执行,中间不会被其他命令打断。
-
EVAL是入口,脚本内容和 key 参数要严格对应,key 必须显式传入,不能硬编码在 Lua 里 - 脚本里用
redis.call("GET", KEYS[1])读,用redis.call("DECR", KEYS[1])扣,别用INCRBY -1——语义不清,容易看错 - 返回值建议用
if stock > 0 then return 1 else return 0 end,让客户端靠数字判断成败,别返回字符串
用 LPUSH + BRPOP 做队列,但别直接丢订单进 Redis 队列
秒杀请求量大时,如果每个请求都 LPUSH 一条订单数据到 Redis 队列,Redis 内存会暴涨,还可能因单条 value 过大(比如含用户完整信息)拖慢响应。这不是队列不行,是压根没做前置过滤。
真正该进队列的,只是最小必要信息:商品 ID、用户 ID、时间戳。其他字段(收货地址、支付方式)等消费端从下游 DB 补全。

