活动结束后库存显示负 37,日志里同一商品在同一毫秒有五条扣减成功的记录,数据对不上。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

redis-cli --eval decr.lua stock:1001
GET stock:1001
# decr.lua 里判断与 DECR 在同一脚本

判断和扣减发成了两条独立命令,中间插进了别的请求,大家读到同一个旧库存,判断都通过后各自减一,超卖就这样发生了。这一点先确认清楚,后面就不用反复试。

「Redis 库存扣减」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。

动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

具体做法是,判断与扣减写进同一段 lua 由服务端一次执行完;返回值要能区分成功、库存不足和重复请求三种情况;落库阶段再用数据库的唯一约束兜住最后一层。

改完照着核一遍,再跑一轮压测,库存结束值为 0,不出现负数也不丢单。

作者 9823189