MGET 只支持字符串类型,对 hash、list、zset 等结构返回 nil 或 WRONGTYPE 错误;读 hash 用 HMGET,list 用 LRANGE,zset 用 ZRANGEBYSCORE;类型不兼容,需用 Lua 脚本做 TYPE 判断+分支调用。

为什么不能直接用 MGET 抓多类型数据
因为 MGET 只能取字符串类型的值,遇到 hash、list、zset 这类结构,它返回 nil 或报错 WRONGTYPE Operation against a key holding the wrong kind of value。你不是数据没存对,是命令用错了类型。
-
MGET本质是批量GET,只认string - 想读
hash里的多个字段,得用HMGET;读list某段用LRANGE;读zset分数区间得用ZRANGEBYSCORE - 不同结构的命令不兼容,没法靠一个命令统一处理
用 Lua 脚本做“类型路由”的实际写法
Lua 脚本在 Redis 里是原子执行的,且能调用所有服务端命令,适合做类型判断 + 分支读取。关键不是“写多酷的脚本”,而是怎么让逻辑清晰、不踩类型误判的坑。
- 先用
TYPE查键类型,再分支:比如if type == "hash" then return redis.call("HMGET", KEYS[1], unpack(ARGV)) - 别用
redis.call("GET", ...)硬试——一旦键是list,脚本直接报错中断 - 参数设计要明确:
KEYS[1]是目标键名,ARGV放字段名或索引范围(如"field1","field2"或"0","-1") - 示例片段:
if redis.call("TYPE", KEYS[1]) == "hash" then return redis.call("HMGET", KEYS[1], unpack(ARGV)) elseif redis.call("TYPE", KEYS[1]) == "string" then return {redis.call("GET", KEYS[1])} else return {} end
批量读多个键+多种类型时的性能和边界问题
一次 Lua 调用里处理太多键或太深的嵌套结构(比如遍历大 zset 再逐个 ZSCORE),容易触发 Redis 的慢日志或超时。这不是 Lua 多慢,是阻塞主线程的代价被放大了。
- 单次脚本建议控制在 10 个键以内,每个键的操作尽量扁平(避免 for 循环套 call)
- 如果要读 5 个
hash的不同字段,别写成 5 次HMGET,改用redis.call("HMGET", KEYS[i], ...)循环,但注意KEYS和ARGV长度限制(Redis 默认 1024 参数) - 空键或不存在的字段会返回
nil,Lua 里要显式转成空字符串或默认值,否则客户端解析可能出错 - 集群模式下,所有
KEYS必须落在同一个 slot,否则报错CROSSSLOT Keys in request don't hash to the same slot
调试 Lua 脚本时最常卡住的地方
错误信息往往只显示 (error) ERR Error running script,没堆栈、没行号,根本不知道哪崩了。这时候得靠“分段注释 + 小步验证”来定位。
- 先把
TYPE结果return出来,确认键类型是不是你预期的(比如你以为是hash,其实是string) - 别在脚本里拼接复杂字符串传给
call,例如redis.call("HMGET", KEYS[1], ARGV[1]..","..ARGV[2])——HMGET不接受逗号拼接的字段列表,必须是独立参数 - 本地测试用
redis-cli --eval,但注意 Windows 下换行符和空格容易引发语法错误,建议先用redis-cli SCRIPT LOAD加载再EVALSHA调用 - 生产环境别用
redis.log()打印调试信息,它不输出到控制台,只进 Redis 日志且需配置loglevel verbose

















