Redis Lua脚本中所有命令返回值均为字符串,须用tonumber()转换并校验;客户端泛型需与脚本return类型严格匹配;ARGV/KEYS全为字符串,浮点数和超大整数不被原生支持。

redis.call() 返回值全是字符串,别直接算术运算
Redis 命令返回值(比如 redis.call("get", "k")、redis.call("hget", "h", "f"))在 Lua 脚本里**永远是字符串类型**,哪怕存的是数字。直接写 local x = redis.call("get", "k") + 1 会报 attempt to perform arithmetic on a string value。
- 所有 Redis 命令返回值都走「Redis 协议 → Lua 字符串」单向转换,没有例外
-
tonumber()是唯一可靠转换方式,但必须检查返回值是否为nil:比如tonumber("abc")返回nil,后续用它做加法仍会崩溃 - 推荐写法:
local val = redis.call("get", "k"); local n = tonumber(val) or error("invalid number: " .. tostring(val))
Jedis / Lettuce 客户端接收 Lua 返回值时类型不匹配
Java 客户端(如 Jedis、Lettuce)对 Lua 脚本的返回值做了自动类型映射:返回数字 → Java Long,返回数组 → List<Object>,返回字符串 → String 或 byte[]。若声明的泛型和实际返回类型不符,就会抛 ClassCastException。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 常见错误:
DefaultRedisScript<String>接收return 1,结果 Jedis 返回Long,强转失败 - 两种解法:① 改客户端泛型(如用
Long.class接数值);② 改脚本,统一返回字符串:return tostring(1)或return "1" - Lettuce 报
ValueOutput does not support set(long)就是典型泛型错配,必须确保DefaultRedisScript的泛型与脚本return类型一致
ARGV 和 KEYS 全是字符串,传数字也得 tonumber()
客户端传进来的 KEYS 和 ARGV 参数,无论你 Java 侧传的是 int 还是 String,到了 Lua 里统统是字符串。指望 ARGV[1] == 123 或直接参与计算,一定会出错。
-
redis.call("incrby", "k", ARGV[1])中,如果ARGV[1]是字符串"10",Redis 内部能隐式转,但如果是"10.5"或"abc"就报错 - 安全做法:开头就校验并转换,例如
local step = tonumber(ARGV[1]) or error("ARGV[1] must be number") - 注意:
tonumber("1e5")在标准 Lua 里合法,但在 Redis 7.0+ 可能被截断为100000后再转回字符串,科学计数法语义丢失
浮点数和超大整数在 Redis Lua 里根本不存在
Redis 的嵌入式 Lua 解释器不支持原生浮点数运算,所有数字按双精度整数处理;但超出 JavaScript 安全整数范围(2^53)或带小数点的值,Redis 会强制转成字符串返回,且可能静默截断或报错。
-
redis.call("set", "k", 3.14)成功,但redis.call("get", "k")拿到的是字符串"3.14",不是数字 - Redis 7.0+ 对
2^53 + 1这类超范围整数更严格:不再静默转字符串,而是直接抛ERR Error running script - 需要精确浮点计算?别在 Lua 里做——把原始数据取出来,在客户端算完再塞回去
tonumber(),而是你以为 type(x) == "number" 能区分“Redis 返回的字符串数字”和“真正数字”。它不能。来源决定类型,不是值长得像不像数字。

















