evalsha调用必须使用script load返回的完整sha1哈希值,而非脚本id或名称;传入错误sha1会报noscript错误,且sha1大小写敏感、不可带空格或引号。

用 EVALSHA 调用已加载脚本,不是“脚本ID”而是 SHA1 哈希值
Redis 没有“脚本ID”概念,实际用的是脚本内容的 SHA1 哈希值(32位十六进制字符串)。调用已加载脚本必须用 EVALSHA,不能用任意 ID 或名称。
-
EVALSHA的第一个参数必须是SCRIPT LOAD返回的完整 SHA1 值,比如c686f316aaf1eb01d7a4c1ae86f7d2b9c0f5f4f3 - 如果传入错误或不存在的 SHA1,会报错:
NOSCRIPT No matching script. Please use EVAL. - SHA1 是大小写敏感的,且不能带引号或空格(
redis-cli中直接粘贴即可)
SCRIPT LOAD 后必须手动记录 SHA1,Redis 不提供命名映射
Redis 不维护脚本名到 SHA1 的映射表,每次 SCRIPT LOAD 返回的 SHA1 就是唯一凭据。你得自己存下来——硬编码、配置文件、启动时预加载并缓存到内存里都行。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 常见做法:服务启动时执行
SCRIPT LOAD,把返回的 SHA1 存进常量或 Spring Bean - 别依赖 Redis 自动记住“哪个 SHA 对应哪个业务逻辑”,它只认哈希,不认语义
- 如果脚本内容哪怕多一个空格,SHA1 就完全不同,会被当作新脚本重新加载
Spring Boot 中 stringRedisTemplate.execute() 默认走懒加载,容易触发 NOSCRIPT 异常
Spring Data Redis 的 execute() 方法底层先尝试 EVALSHA,失败后自动 fallback 到 EVAL,但这个 fallback 仅发生在**第一次调用时**。
- 问题场景:新部署环境、Redis 集群重建、
SCRIPT FLUSH后,首个请求仍可能因并发导致多个线程同时 fallback,造成重复EVAL和脚本重复加载 - 更稳的做法:在应用启动阶段主动调用
redisTemplate.getConnectionFactory().getConnection().scriptLoad(...)预热 - 注意:Cluster 环境下需确保脚本加载到所有分片节点(Spring Boot 2.6+ 默认支持自动广播)
脚本加载和调用必须保证 key 分布一致,尤其在 Redis Cluster 下
Redis Cluster 要求脚本中所有 KEYS 参数必须落在同一个 slot,否则 EVALSHA 会直接报错 CROSSSLOT Keys in request don't hash to the same slot。
- 写脚本时,所有操作的 key 必须通过
KEYS[1]、KEYS[2]传入,禁止硬编码 key 名(如redis.call('GET', 'user:1001')) - 调用时,
numkeys必须等于KEYS数组长度,且这些 key 必须属于同一哈希槽(通常靠业务 key 设计保证,比如用{user}:1001形式) -
ARGV可以任意传,不参与 slot 计算,适合传 value、过期时间等非 key 数据
EVALSHA 表面能跑,线上一压就出错。










