REDIS · LUA 原子合约
库存 Lua 合约实验台
把“读库存、查 token、判断条件、写结果”压进一次不可穿插的执行。改变参数并重复请求,观察脚本到底在哪个分支停下。
READ → WRITE
执行期间不被其他命令插入
GET stock:sku-1001
12件可售
SMEMBERS stock:processed
尚无已处理 token
本次原子执行轨迹
等待运行KEYS[1] · 库存 key
stock:sku-1001KEYS[2] · 已处理集合
stock:processedARGV[1] · 扣减量
"3"ARGV[2] · 请求 token
"order-2026-001"- 1校验 ARGV扣减量必须是正整数,token 不能为空待执行
- 2SISMEMBER 检查 token已经处理过就直接返回,不再扣库存待执行
- 3GET 并判断库存可售库存必须大于或等于本次扣减量待执行
- 4SADD 记录 token标记请求已被脚本接纳待执行
- 5DECRBY 扣减库存写入扣减后的可售数量待执行
—
尚未返回
{ code: null, stock: 12, token: null }
原子执行解决“被插队”,不等于事务回滚
Redis 会从脚本第一条命令执行到最后一条,期间不会穿插另一个客户端的命令。因此两个请求不会同时读到同一份库存再各自扣减。
但脚本运行时报错不会回滚。勾选错误注入后,SADD 已经成功写入的 token 会保留,后面的 DECRBY 没有执行。真正的脚本应把参数校验放在任何写操作之前,并谨慎安排写入顺序。
结构化返回码
- 1
- 扣减成功,返回剩余库存
- 0
- 库存不足,状态未改变
- 2
- 重复请求,幂等命中
- -1
- 参数非法,拒绝执行
- ERR
- 脚本运行时错误,已写命令不回滚