redis lua脚本支持标准lua控制结构,但需严防死循环和nil误判:if必须用==比较、显式处理nil,while循环须有安全退出条件,避免因ttl返回-1/-2等导致无限循环。

Redis Lua 脚本里能用标准 Lua 的 if/elseif/else 和 while/for,但必须注意:Redis 服务端执行时没有超时中断机制,写死循环或条件永远为真会导致整个 Redis 实例卡住。
if 判断必须用 == 而不是 =,且 nil 要显式处理
Lua 中赋值用 =,比较用 ==。写成 if redis.call("get", KEYS[1]) = "ok" then 是语法错误,直接报 ERR Error compiling script (value is not a valid number) 或更模糊的 ERR Error running script。
另外,redis.call("get", ...) 返回的是字符串,但如果 key 不存在,返回的是 nil,而 nil == "xxx" 永远是 false,不会报错,但逻辑可能意外跳过:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 用
type()或redis.call("exists", KEYS[1]) == 1显式判断 key 是否存在 - 字符串比较前先检查是否为
nil,比如:local val = redis.call("get", KEYS[1]); if val ~= nil and val == ARGV[1] then ... -
tonumber()对nil返回nil,再参与数值比较会出错,务必前置判空
while 循环必须有明确退出条件,避免无限循环
Redis 不提供 break 或 return 跳出循环体的快捷方式(Lua 本身支持 break,但脚本中一旦卡住就只能 kill 进程),所以 while 循环必须靠变量递增/递减 + 显式 if ... break 控制:
- 不要写
while true do ... end,哪怕加了内部if也不保险 —— 条件判断出错就锁死 - 计数器要初始化、递增,并和上限比较,例如:
local i = 0; while i - 每次循环内尽量只调用轻量命令;频繁
redis.call("hgetall", ...)可能因数据量大拖慢整体执行,间接延长循环时间
for 循环遍历数组时,KEYS 和 ARGV 索引从 1 开始
Lua 表默认索引从 1 开始,但新手常误以为像 JavaScript 那样从 0 开始,导致取错参数:
-
KEYS[1]是第一个键名,ARGV[1]是第一个额外参数,不是ARGV[0] - 遍历所有键:
for i = 1, #KEYS do redis.call("del", KEYS[i]) end,#KEYS才是长度 - 遍历所有参数:
for i = 1, #ARGV do ... end,别写成for i = 0, #ARGV - 1 - 如果传了 0 个 key,
#KEYS是 0,循环体一次都不执行,这是预期行为
最危险的不是语法写错,而是逻辑上没兜底 —— 比如用 while redis.call("ttl", KEYS[1]) > 0 do ...,但 TTL 返回 -1(永不过期)或 -2(key 不存在)时,条件永远成立。这类细节不验证,上线后就是线上事故。










