Go中用go-redis执行Lua脚本需用Script.Run()自动EVALSHA以提升性能30%以上,首次须SCRIPT LOAD;动态脚本退化为Eval但需控长防超时;参数传递须严格匹配KEYS/ARGV顺序与类型,调试优先用redis-cli eval。
直接在 Go 中用
执行 Lua 脚本,能避免多次网络往返、保证原子性,但不是所有场景都适合——关键看脚本是否读写同一组 key、是否依赖 Redis 内部状态(比如
),否则容易踩超时、沙箱限制或结果类型不匹配的坑。
为什么必须用
而不是反复
Redis 会缓存已加载的 Lua 脚本 SHA1 值,
复用缓存后,性能比每次传完整脚本的
高 30% 以上。但首次执行必须先
,否则返回
错误。
Go 中推荐用
加载一次,再用
(内部自动用
)
不要手动拼接
+
,
的
类型已封装好容错逻辑
如果脚本内容动态生成(比如带变量插值),就不能用
对象,得退回到
,但此时务必控制脚本长度,避免触发
超时
的参数传递规则很严格
Lua 脚本里通过
、
访问参数,而
的第 3 个参数是
,第 4 个是
。顺序错、类型错、空切片处理不当都会导致脚本报错或逻辑异常。
Redis 8.2.3
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
下载
必须是非空切片,哪怕只用一个 key,也要传
,不能传
或空字符串
中的
、
会被转成 Lua number,
变成 string,但
会变成 Lua
,而
不接受
作参数
如果需要传 JSON 或复杂结构,先在 Go 侧
成字符串,再在 Lua 里用
(需 Redis 启用
模块)
本地调试 Lua 脚本比在 Go 里试错快得多
Redis CLI 的
命令支持快速验证逻辑,还能用
输出调试信息(日志出现在 Redis 的
及以上)。
CLI 示例:
(注意逗号前后空格,左边是 keys,右边是 args)
Go 中捕获错误时,别只打印
,要检查
是否为
,然后用
看原始 Redis 错误,比如
脚本中避免用
这类循环,如果
为空,
是 0,循环不会执行——但你可能预期它报错提示缺失 key
最常被忽略的是脚本超时和内存限制:Redis 默认
(毫秒),且不允许脚本分配超过 10MB 内存。一旦触发,Redis 会强制中断并返回
或
,此时 Go 侧收到的是连接错误而非 Lua 异常,需要单独处理重试或降级逻辑。
go-redisredis.call("GET", ...)EVALSHAEVALEVALSHAEVALSCRIPT LOADNOSCRIPTredis.Script.Load().Run()redis.Script.Run()EVALSHASCRIPT LOADEVALSHAgo-redisScriptScriptEvallua-time-limitScript.Run()KEYS[1]ARGV[1]Script.Run()keys []stringargs ...interface{}keys[]string{"user:123"}nilargsintfloat64stringnilnilredis.call()niljson.Marshalcjson.decode()cjsonevalredis.log()loglevel noticeredis-cli --eval ./incr_with_limit.lua user:123 , 100 10err.Error()err*redis.RedisError.Error()(error) ERR Error running script (call to f_...): @user_script:3: user_script:3: attempt to compare number with nilfor i=1, #KEYS doKEYS#KEYSlua-time-limit 5000BUSYOOM