EVALSHA 报 NOSCRIPT 是因 Redis 未缓存对应 SHA1 值;SHA1 必须是 SCRIPT LOAD 返回的完整40字符小写十六进制串,且需发至目标 slot 节点,主从切换后需重载脚本。

EVALSHA 报 NOSCRIPT 不是脚本写错了,而是 Redis 根本没“见过”这个脚本。它只认 SHA1 哈希值,且必须是 SCRIPT LOAD 返回的原始 40 字符小写十六进制字符串——错一位、多一个空格、大小写混用、加引号,全都会触发 NOSCRIPT No matching script. Please use EVAL.。
SCRIPT LOAD 返回的 SHA1 必须原样复用
Redis 不提供“脚本名 → SHA1”映射,也不接受任何别名或缩写。你拿到的 SHA1 就是唯一钥匙:
-
SCRIPT LOAD "return redis.call('GET', KEYS[1])"返回c686f316aaf1eb01d7a4c1ae86f7d2b9c0f5f4f3,那就得用这个完整字符串调用EVALSHA - 不能截取前 8 位(如
c686f316),不能转成大写(C686F316...),不能包在引号里传给 redis-cli - 脚本内容哪怕改一个空格,SHA1 就变,Redis 当作全新脚本,旧 SHA 立刻失效
集群环境下 SCRIPT LOAD 必须发到目标 slot 节点
Redis Cluster 不共享脚本缓存,每个分片独立维护自己的 lua_scripts 字典:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 如果你对 key
{user}:1001执行脚本,SCRIPT LOAD必须发到该 key 所在 slot 的节点(比如 12345 号 slot 对应 node-A) - 若误发到 node-B,node-B 缓存里没有该 SHA,后续
EVALSHA到 node-B 就报NOSCRIPT - Spring Boot 2.6+ 默认开启自动广播,但前提是脚本加载时显式指定
keys参数,否则仍可能漏节点
哨兵切换后脚本缓存不会自动同步
主从切换时,Lua 脚本不参与复制流程,新主库(原从库)的缓存是空的:
- 旧主库上
SCRIPT LOAD成功,不代表新主库也“记得”这个 SHA - 客户端继续用老 SHA 发
EVALSHA,新主库直接返回NOSCRIPT,不是连接异常,是明确拒绝 - SCRIPT FLUSH 更危险:在切换窗口期执行,会导致旧主丢脚本、新主没脚本,全线崩
真正难处理的从来不是 Lua 语法,而是 SHA1 的生命周期管理——它既不持久化,也不跨节点,还不随主从漂移。每次部署、重启、切主,都得重新确认脚本是否真在目标节点上活着。

















