redis 6.x与7.x的lua脚本执行机制基本一致,eval/evalsha语法、keys/argv传参及lua 5.1解释器行为完全兼容;差异在于7.x强化了集群中script load预加载要求、错误处理更严格、超时无回滚行为易被误读,且redis functions不可直接迁移eval脚本。

Redis 6.0 和 7.0 的 Lua 脚本执行机制基本一致,EVAL 和 EVALSHA 命令语法、KEYS/ARGV 传参方式、Lua 5.1 解释器行为完全兼容——你在 6.2 写好的脚本,原样发给 7.4 就能跑通。真正需要你动手调整的,是部署逻辑、错误处理边界和集群行为。
为什么 EVALSHA 在 Redis 7.x 集群中频繁报 NOSCRIPT?
不是脚本本身出错,而是 7.x 对脚本加载状态做了更严格的校验:所有分片节点必须已通过 SCRIPT LOAD 预加载过对应 SHA1,否则直接返回 NOSCRIPT;而 6.x 某些客户端驱动会静默 fallback 到 EVAL(不推荐但存在)。
- 客户端必须主动捕获
NOSCRIPT错误,再触发SCRIPT LOAD+EVAL重试流程,不能依赖服务端兜底 - 集群扩缩容后,新节点不会自动同步已加载脚本,需在部署阶段显式调用
SCRIPT LOAD或使用redis-cli --eval初始化 -
SCRIPT FLUSH会清空所有节点的脚本缓存,若未同步 reload,后续EVALSHA必然失败
lua-time-limit 超时后,部分命令已执行却无法回滚
这个行为在 6.x 和 7.x 完全相同,但 7.x 更强调“服务端逻辑可靠性”,容易让人误以为超时会自动回滚。实际上,超时中断后,已成功执行的 redis.call('XADD', ...)、redis.call('SET', ...) 等操作不会撤销。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
lua-time-limit默认仍是 5000ms,修改需在redis.conf中显式配置 - 脚本内不应依赖“超时 = 全部未生效”,涉及多 key 修改时,建议前置校验或用事务包装可逆操作
- 日志类辅助操作(如
redis.log())在FUNCTIONS中已被禁用,但传统EVAL仍可用
Redis Functions 不是 EVAL 的无缝替代品
不能把一段 EVAL "return redis.call('GET', KEYS[1])" 1 mykey 直接塞进 FUNCTION LOAD。函数模型和脚本模型是两套抽象:
-
FUNCTION LOAD要求带#!lua name=xxx前缀,且必须用redis.register_function(name, fn)显式注册入口函数 - 函数参数是解析后的
keys和args数组,不再有原始KEYS[1]这种索引语义 - 函数不支持
redis.sha1hex()、redis.log()等非安全函数,也无法访问全局变量 - 函数持久化到 RDB/AOF 并自动集群同步,但迁移成本高:需重写逻辑、测试权限、管理生命周期
真正容易被忽略的是:脚本管理成本没消失,只是从客户端转移到了服务端——FUNCTIONS 要求你像维护模块一样做版本、灰度、回滚,而 EVALSHA 的坑集中在部署时漏加载、集群不同步、超时副作用这三处。










