Redis 5.0如何解决主从切换后的Lua脚本丢失问题_解析脚本复制与指令复制

云丽小哥_1799

云丽小哥_1799

2026-06-19

727人浏览

原创

redis 5.0 主从切换后 lua 脚本“失效”的根本原因是 eval 命令默认以指令复制方式同步,从节点未预加载脚本,导致 evalsha 报 noscript 错误;启用 lua-replicate-commands yes 可强制先 script load 再 evalsha,确保脚本体在从节点存在。

redis 5.0如何解决主从切换后的lua脚本丢失问题_解析脚本复制与指令复制

Redis 5.0 主从切换后 Lua 脚本不会“丢失”,但可能因复制机制不一致导致执行失败或结果不符——根本原因不是脚本本身消失,而是 EVAL 命令在主从间以“指令复制”(而非“脚本复制”)方式同步,且从节点未提前加载脚本。

为什么主从切换后 Lua 脚本看似“失效”

Redis 5.0 默认使用指令复制(replica-serve-stale-data yes + repl-backlog-size),即主节点把 EVAL "..." N key1 key2 这条命令原样发给从节点执行,而不是把脚本体先 SCRIPT LOAD 到从节点。这意味着:

  • 如果主节点刚执行过一次 EVAL,从节点能复现结果(因为指令被完整复制并执行)
  • 但如果主节点用 EVALSHA 执行一个未在从节点注册的 SHA1,从节点会返回 NOAUTH 或 NOSCRIPT 错误
  • 主从切换后,新主节点(原从节点)自身没执行过该脚本,SCRIPT EXISTS 查不到 SHA,EVALSHA 必然失败
  • 客户端若只依赖 EVALSHA 且无 fallback 到 EVAL 的逻辑,就会报错

必须启用 script-loading 复制才能保障一致性

Redis 5.0 支持通过配置开启脚本体的显式复制,让从节点在收到 EVAL 前先自动执行 SCRIPT LOAD。关键配置项是:

在主节点 redis.conf 中设置:
lua-replicate-commands yes

这个参数的作用是:当启用时,Redis 会把每次 EVAL 拆成两步复制 —— 先发 SCRIPT LOAD(含完整脚本字符串),再发 EVALSHA。这样从节点始终拥有脚本体,主从切换后也能直接执行 EVALSHA。

注意:
• 该选项仅对 EVAL 生效,不影响已存在的 EVALSHA 调用
• 必须主从都运行 5.0+ 且配置一致,否则从节点忽略该 flag
• 若关闭(默认为 no),则完全依赖指令复制,风险如上所述

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载

客户端必须实现 EVAL / EVALSHA 双路 fallback

即使服务端开启了 lua-replicate-commands yes,生产环境仍需客户端兜底。常见错误写法是硬编码调用 EVALSHA 并假设脚本一定存在。

安全做法应为:

  • 首次调用某脚本时,先发 SCRIPT LOAD 获取 SHA,缓存到本地(如内存 Map 或 Redis 自身的 SETNX 兜底)
  • 后续统一走 EVALSHA,但捕获 NOSCRIPT 错误
  • 捕获到 NOSCRIPT 后,立即重试 SCRIPT LOAD + EVALSHA(不是回退到 EVAL,避免重复传输大脚本)
  • 避免在事务(MULTI/EXEC)中混用 EVAL 和 EVALSHA,Cluster 模式下可能跨 slot 导致失败

Redis Cluster 下还有额外限制要绕开

如果你用的是阿里云 Redis 版(5.0.8 以下)或原生 Redis Cluster,EVAL 脚本中的所有 key 必须落在同一哈希槽,且必须通过 KEYS[1] 等显式引用,不能拼接、不能用 ARGV 传 key,否则报错:
-ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array

典型翻车点:

  • redis.call('get', 'foo') → 错,key 字符串字面量不被允许
  • redis.call('get', ARGV[1]) → 错,ARGV 不是 key 来源
  • local k = KEYS[1] .. ':sub'; redis.call('get', k) → 错,动态构造 key 不被识别为合法 key
  • 正确写法只有:redis.call('get', KEYS[1]),且调用时 EVAL "...", 1 foo

这个限制和主从切换无关,但在切换后因连接池重连、客户端重试逻辑混乱,更容易暴露出来。

相关专题

更多
常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4289

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

3795

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

6892

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

623

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

736

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

6522

6

redis缓存一般存些什么数据
redis缓存一般存些什么数据

redis缓存中存储的数据类型包括:字符串、哈希、列表、集合、有序集合、位图、地理空间数据和hyperloglog。这些数据类型适用于存储各种数据,从简单信息到复杂对象和地理位置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1140

6

redis的8种数据类型有哪些
redis的8种数据类型有哪些

redis 提供 8 种数据类型:字符串(文本、数字、二进制)、哈希(键值对)、列表(有序集合)、集合(无序唯一元素)、有序集合(按分数排序)、地理空间(地理位置)、hyperloglog(估计大数据基数)和位图(位序列存储)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1016

6

redis主要作用有哪些
redis主要作用有哪些

redis 的主要作用包括:1. 缓存数据,提高访问速度;2. 充当消息队列,实现消息传递;3. 存储各种数据类型,如字符串、散列和集合;4. 管理会话信息,确保可靠性和可用性;5. 限制请求速率,防止服务器超载等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

5798

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习