一眼识别redis被lua脚本卡死需同时查看info中三项指标:lua_script_busy=1表示有脚本运行;used_memory_rss_human稳定不变说明纯计算,持续上涨则可能构造大表;cmdstat_eval:usec_per_call超500万微秒且calls不增基本确认卡死。

怎么一眼看出Redis正在被Lua脚本卡死
直接执行 redis-cli INFO | grep -E "(lua_script_busy|used_memory_rss_human|cmdstat_eval)",三处指标必须一起看:
-
lua_script_busy:1表示有脚本在跑,但不等于能 kill —— 它只是“正在运行”的快照 -
used_memory_rss_human如果稳定不变(比如一直停在 256MB),说明脚本纯计算、没分配新内存;如果持续上涨,大概率在构造大 table 或反复调用redis.call -
cmdstat_eval:usec_per_call若长期 >5000000(即超 5 秒),且calls不再增长,基本坐实卡死
别只信 lua_script_busy —— 它可能刚从 1 变回 0,而脚本其实已进入不可中断阶段,INFO 统计却还没刷新。
SCRIPT KILL 为什么输完就卡住或返回 BUSY
SCRIPT KILL 不是“一键终止”,它只在两个前提下生效:脚本尚未执行任何写命令,且未超 lua-time-limit(默认 5000ms)。
- 返回
(error) BUSY Redis is busy running a script...:说明脚本已超时,被标记为 BUSY,但你还连在错误节点上(集群常见)或主线程已被完全霸占,命令发出去根本没机会被处理 - 命令卡住无响应:主线程正陷在
while true do end里,连SCRIPT KILL的解析和路由都做不了 - 返回
(error) UNKILLABLE Sorry the script already executed write commands:脚本已调用过redis.call("SET",...)等写操作,Redis 主动拒绝中断,这是数据一致性保护,不是 bug
此时再试 SCRIPT KILL 没意义 —— 它不是失效,是压根不该起作用。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
确认脚本是否还能 kill 的最小验证法
不要盲目重试 SCRIPT KILL,先用一个极简只读脚本探路:
redis-cli --eval /dev/stdin 0 <p>这个脚本能秒回,说明实例响应通道还通、未写入;如果也卡住,基本可判定脚本已执行写命令或彻底锁死主线程,<code>SCRIPT KILL</code> 无效。</p>
- 成功返回
(integer) 0→ 可尝试SCRIPT KILL - 卡住或超时 → 放弃
SCRIPT KILL,准备走SHUTDOWN NOSAVE - 返回其他错误(如
NOAUTH)→ 权限问题,不是阻塞本身
集群环境下特别容易踩的坑
在 Redis Cluster 中,SCRIPT KILL 必须发给真正执行该脚本的节点 —— 而不是你随手连的那个 proxy 或任意 master。
- 用
redis-cli -c连集群时,EVAL会自动路由,但SCRIPT KILL不会自动转发,它只作用于当前连接的节点 - 先查
CLUSTER NODES找出疑似卡死节点的 IP:PORT,再单独连过去执行SCRIPT KILL - 如果脚本涉及多个 key,且
KEYS数组跨 slot(触发CROSSSLOT错误),脚本根本不会启动,也就不存在“卡死”——这种是语法/路由错误,不是死循环
最麻烦的是:脚本卡在某个 master 上,但你的监控只扫了 slave 或 coordinator,根本看不到真实负载。定位必须落到具体节点的 INFO 和 CLIENT LIST 输出上,不能靠猜。










