首页/数据/Redis 进阶速查/NOSCRIPT:脚本缓存未命中
性能与排障129 条

NOSCRIPT:脚本缓存未命中

EVALSHA 的脚本哈希不在缓存(实例重启或 SCRIPT FLUSH 后)时报 NOSCRIPT;标准处理是用 EVAL 回退重新加载一次。

Redis 进阶速查数据更新于 2026-10-13

NOSCRIPT 错误是什么

用 EVALSHA 调用脚本时,如果实例缓存里没有这个 SHA1,就会返回 NOSCRIPT No matching script. Please use EVAL。脚本缓存不随重启保留,所以实例重启、滚动升级、执行过 SCRIPT FLUSH 之后的第一批调用最容易撞上它。标准处理是回退用 EVAL 提交脚本体,缓存重建后继续用 EVALSHA。

基本信息

错误文本NOSCRIPT No matching script. Please use EVAL
触发条件缓存中没有对应 SHA1(重启、清缓存后)
检查命令SCRIPT EXISTS <sha1>…
预加载SCRIPT LOAD <脚本文本>
客户端处理捕获 NOSCRIPT 后用 EVAL 回退并重建缓存
集群注意脚本缓存是节点级的,需逐节点预加载或依赖回退

典型使用场景

  • 实例重启后批量报错:滚动重启期间走 EVALSHA 的调用会失败一次,靠回退自愈
  • 发布前预加载:把脚本体当固定资源,启动流程里 SCRIPT LOAD 后拿到 SHA
  • 自研客户端加固:确认实现里捕获了 NOSCRIPT 并回退 EVAL
  • 集群环境:确认每个分片节点都能命中脚本,或依赖回退兜底
  • 排障区分:回退后仍失败说明是脚本体本身的问题,不是缓存问题

最小示例

最小示例
redis-cli SCRIPT EXISTS 5f6b1f9c0f1f...      # 检查脚本是否还在缓存
redis-cli SCRIPT LOAD "$(cat script.lua)"     # 预加载并得到 SHA1
redis-cli EVALSHA 5f6b1f9c0f1f... 1 mykey     # 用 SHA 调用
redis-cli SCRIPT FLUSH                        # 清空缓存,之后 EVALSHA 会报 NOSCRIPT
redis-cli --cluster call <node:port> SCRIPT LOAD "$(cat script.lua)"   # 集群逐节点预加载

阶段与现象

阶段现象处理
首次调用只有 SHA 没有脚本体用 EVAL 提交一次后缓存建立
重启后首调用报 NOSCRIPT客户端回退 EVAL 重建缓存
清缓存之后全部 EVALSHA 报错有回退则自动恢复,无回退需人工介入
集群跨节点其他节点也报 NOSCRIPT逐节点预加载,或依赖回退
脚本体本身有问题回退 EVAL 依然失败属于脚本语法或逻辑问题,与缓存无关
主流客户端库都内置了 NOSCRIPT 回退:收到该错误时自动改用 EVAL 提交脚本体。自研客户端必须自己实现这一步。
把脚本体当固定资源管理(版本化、启动时预加载),既能减少首调用失败,也避免动态拼接导致缓存条目无限增长。

易错点

  • 自研客户端没有回退逻辑:实例重启后所有 EVALSHA 调用持续失败,直到缓存被人为重建
  • 集群只在一个节点上预加载脚本:其他节点照样报 NOSCRIPT,缓存是节点级的
  • 频繁清空脚本缓存:正在跑的业务调用被打断,表现为成片的脚本错误
  • 把 NOSCRIPT 当一次性抖动:回退后仍失败说明是脚本体本身有问题,别只盯缓存
  • 上线前不预加载:首调用抖动与失败直接暴露给用户请求

数据来源与参考

  • Redis 官方文档:EVALSHA 与脚本缓存
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌