首页/数据/Redis 进阶速查/Lua 脚本的限制与超时行为
数据结构与选型42 条

Lua 脚本的限制与超时行为

脚本执行期间服务器被独占,默认 lua-time-limit 5 秒只用于打日志;超时后仅允许 SCRIPT KILL(未写数据时)或 SHUTDOWN NOSAVE 中断。

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

脚本的原子性与阻塞代价

Lua 脚本在 Redis 中是原子执行的:整段脚本运行期间,服务器不会处理其他命令。这带来强一致性,也带来风险——脚本写得越重,阻塞时间越长,所有客户端一起等。lua-time-limit 默认 5000 毫秒,但它只用于打日志和让客户端感知超时,并不会强制终止执行中的脚本。超过该时间后,其他客户端会收到 BUSY 错误,此时只剩两条处置路径:脚本尚未写入数据时可以 SCRIPT KILL 终止,已经写入就只能停机评估重放。

基本信息

默认限制lua-time-limit 5000 毫秒
超时表现其他客户端收到 BUSY 错误
可执行操作SCRIPT KILL(仅未写数据时)、SHUTDOWN NOSAVE
复制方式5.0 起的默认效果复制以数据变更为准
脚本管理SCRIPT LOAD / SCRIPT EXISTS / SCRIPT FLUSH

典型使用场景

  • 用脚本实现原子业务逻辑(库存扣减、限流、分布式锁)时评估阻塞边界
  • 线上出现 BUSY 报错,定位是哪段脚本在长时间运行
  • 代码评审:确认脚本里没有全量遍历或大批量循环
  • 灰度发布前做压测,确认脚本在目标数据规模下的 P99 耗时
  • 事故处置时判断该用 SCRIPT KILL 还是直接停机

超时后的处置

超时后的处置
redis-cli CLIENT LIST | grep cmd=lua        # 找到正在执行脚本的连接
redis-cli SCRIPT KILL                       # 脚本未写数据时可安全终止
redis-cli SCRIPT KILL                       # 已写数据时会返回 UNKILLABLE
redis-cli SHUTDOWN NOSAVE                   # 最后手段:不保存退出,再评估重放
redis-cli INFO commandstats | grep -i eval  # 平时用调用量与耗时观察脚本开销

超时阶段的行为

阶段服务器表现可执行操作
未超时正常处理所有命令无
超过 lua-time-limit打日志,其他请求得到 BUSY仍可执行 SCRIPT KILL 与 SHUTDOWN NOSAVE
脚本只读未写可安全终止SCRIPT KILL 生效
脚本已写入数据无法终止只能停机,或等脚本自行跑完
脚本里最危险的不是单条命令,而是循环:遍历一个几十万元素的集合,或在脚本里做大段字符串拼接与排序,耗时都会随数据规模线性增长。更稳的做法是把大规模计算放到应用侧,脚本里只保留「条件判断加写入」的核心逻辑。

易错点

  • 在脚本里遍历大集合或做大范围扫描,触发长时间阻塞,所有业务请求一起超时
  • 误以为 lua-time-limit 会自动中断脚本,事故发生时才发现只能停机处理
  • 脚本已写入数据后尝试 SCRIPT KILL,得到 UNKILLABLE 提示,白白消耗处置时间
  • 把耗时的外部计算(复杂排序、大 JSON 解析)塞进脚本,阻塞窗口远超预期

数据来源与参考

  • Redis 官方文档:EVAL 脚本超时与 SCRIPT KILL 说明
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌