redis lua脚本通过keys和argv接收参数:keys存显式声明的key名,argv存动态值参数;必须用argv传递所有非key参数,避免拼接注入,并注意字符串类型转换与空值处理。

Redis Lua脚本里怎么接收外部传进来的参数
Redis 执行 EVAL 或 EVALSHA 时,Lua 脚本能拿到两个固定表:KEYS 和 ARGV。前者存 key 名(必须显式声明),后者存任意值参数——你所有「动态参数」都得走 ARGV。
常见错误是把变量直接拼进 Lua 字符串里传,比如用 Python 的 f-string 把用户输入塞进脚本体,这既危险(Lua 注入)又低效(无法缓存 SHA)。正确做法是:脚本写死逻辑,参数全走 ARGV。
-
KEYS只能用于真正需要 Redis 命令操作的 key,且数量和顺序必须和EVAL命令中 key 参数严格一致 -
ARGV是纯数据容器,支持字符串、数字、nil(但 Redis 客户端通常把 nil 转成空字符串或丢弃) - Lua 里访问参数:取第一个动态值用
ARGV[1],第二个用ARGV[2],下标从 1 开始
用 EVAL 传参时命令格式容易错在哪
执行 EVAL 时,key 数量、key 列表、argv 列表三者位置和数量必须对齐,错一个就报 ERR Error running script (call to f_...): @user_script: N: user_script: N: attempt to concatenate a nil value 这类奇怪错误。
典型翻车点:忘了数 key 个数,或者把本该进 ARGV 的值误塞进了 key 列表。
- 命令结构固定为:
EVAL <script> <numkeys> <key1> <key2> ... <arg1> <arg2> ...</script> -
numkeys是 key 的个数,不是总参数个数;它决定了前几个参数被放进KEYS表,剩下的全进ARGV - 例如:执行
EVAL "return KEYS[1]..ARGV[1]" 1 mykey hello→ 返回"mykeyhello";但写成EVAL "...” 0 mykey hello就会让mykey进ARGV[1],hello进ARGV[2]
Lua 脚本里处理 ARGV 类型要注意什么
Redis 只传字符串给 Lua,哪怕你传的是数字 123 或布尔 true,到 Lua 里都是字符串。脚本里不能直接拿 ARGV[1] > 10 比较,会出错。
常见场景如限流、计数、条件判断,都得手动类型转换,而且得防空值。
- 转数字用
tonumber(ARGV[1]),失败返回nil,务必检查,否则后续运算崩掉 - 转布尔建议靠约定:服务端传
"1"/"0"或"true"/"false",Lua 里写ARGV[1] == "1",别依赖tostring或自动转换 - 如果参数可能为空(比如可选字段),用
ARGV[1] ~= nil and ARGV[1] ~= ""双重判断,因为 Redis 客户端有时把空值转成空字符串
用 EVALSHA 传参和 EVAL 有区别吗
没有本质区别。EVALSHA 只是把脚本内容换成 SHA1 值,参数传递机制完全一样:还是靠 KEYS 和 ARGV,命令格式也一模一样。
唯一多一步:你得先用 SCRIPT LOAD 把脚本加载进 Redis,拿到 SHA 值,再用 EVALSHA 执行。漏掉这步就会报 NOAUTH Authentication required(如果开了认证)或更常见的 NOSCRIPT No matching script. Please use EVAL。
- 调试阶段建议先用
EVAL,确认逻辑没问题再切EVALSHA - 生产环境用
EVALSHA更好:减少网络传输、提升执行速度、避免重复加载 - 注意客户端封装(如 redis-py)可能自动帮你做
SCRIPT LOAD+EVALSHAfallback,但底层逻辑不变,传参方式也不变
最常被忽略的是:参数顺序和数量必须和 numkeys 精确对齐,差一个位置,KEYS 和 ARGV 就全乱了,而 Lua 报错信息根本不提示哪错了。










