redis lua脚本中return true或false均被强制映射为resp nil(客户端收到none/null),因redis仅允许nil、number、string、table作为合法返回类型,boolean被协议层静默归一化;须用table封装(如{return=true})或redis 7.0+ debug error实现语义明确返回。

Redis Lua脚本根本不会把布尔值转成整数返回——它压根不允许 return boolean(true 或 false)作为顶层返回值,而是统一映射为 RESP nil(即客户端收到 None / null)。
为什么 return true 和 return false 都变成 nil?
Redis 的 Lua 执行环境明确禁止直接返回 true 或 false:它们不属于被支持的返回类型集合(只允许 nil、number、string、table、boolean 中的 nil 会被保留,但 true/false 在最终协议编码阶段被强制归一化为 nil)。
-
EVAL "return true" 0→ 客户端收到nil(不是1) -
EVAL "return false" 0→ 客户端同样收到nil(不是0) - 这个行为和 Lua 自身无关,是 Redis 内部对 RESP 协议输出的硬性约束
那为什么有人看到 “返回了 1 或 0”?
常见混淆来源有三个:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 误把
redis.call("EXISTS", "key")的返回值当成了脚本return值:它确实返回1或0(Lua number),但那是命令执行结果,不是你return的布尔值 - 客户端 SDK 做了隐式转换:比如某些旧版
redis-py在 pipeline 场景下把nil自动转成0或空列表,这不是 Redis 行为,是客户端 bug 级别处理 - 用
tonumber()错误转换了false:例如local x = redis.call("GET", "missing"); return tonumber(x),此时x是false,tonumber(false)返回nil,最终仍落回nil,但日志里可能显示 “cannot convert boolean” 被截断误解
想让客户端拿到明确的布尔语义,该怎么做?
必须绕过顶层 boolean 限制,用容器承载:
- 用 table 包一层:
return {ok = true}→ 客户端收到{"ok": True}(Python)或{ok: true}(JS) - 用数组形式:
return {1}→ 客户端收到[1],再由业务解包 - Redis 7.0+ 可主动报错:
redis.call("debug", "error", "invalid input"),客户端捕获异常而非解析返回值 - 绝对不要写
if not val then return false end—— 这等于主动放弃语义区分能力
真正容易被忽略的是:**Redis 对 return 值的类型检查发生在脚本退出前的最后一刻,且不报 warning。你写的 return true 看似合法 Lua,却在协议层被静默“消毒”成 nil,连错误日志都不会打。**










