为什么Redis发布订阅在Slave节点上可以订阅但不能发布_理解读写分离限制

秋辰君_5286

秋辰君_5286

2026-05-27

589人浏览

原创

redis slave节点默认只读,publish命令因属写操作而被拒绝,报错“readonly”;subscribe虽可执行但不可靠,因订阅关系不复制、不跨节点,且消息不通过复制通道转发,故生产环境应统一在master节点进行发布与关键订阅。

为什么redis发布订阅在slave节点上可以订阅但不能发布_理解读写分离限制

Slave节点执行PUBLISH命令直接报错

Redis 的 Slave 节点默认是只读的,这是由 replica-read-only yes(旧版叫 slave-read-only)配置强制控制的。一旦启用(默认开启),所有写命令(包括 PUBLISH)都会被拒绝,返回错误:READONLY You can't write against a read only replica.

注意:这不是 Pub/Sub 机制本身的限制,而是 Redis 复制架构的底层约束——Slave 只负责同步和提供读服务,不参与任何写操作决策,哪怕 PUBLISH 看似“不改数据”,它仍被归类为写命令。

  • PUBLISH 会触发内部事件分发、更新订阅者计数、写入输出缓冲区,这些行为在协议层被标记为写操作
  • 即使你手动关掉 replica-read-only,也**不推荐**让 Slave 执行 PUBLISH——这会导致主从状态不一致(比如消息只发到 Slave 的订阅者,Master 不知道,其他 Slave 也收不到)
  • Slave 上能 SUBSCRIBE 是因为订阅只是注册客户端状态,不修改数据,也不影响复制流

为什么SUBSCRIBE在Slave上能成功但实际不可靠

虽然 SUBSCRIBE 命令在 Slave 节点上能执行成功,但它的行为存在隐性风险:

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

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

下载
  • 订阅关系只存在于当前 Slave 实例内存中,不会同步给 Master 或其他 Slave
  • 如果该 Slave 故障或发生故障转移(failover),所有订阅连接立即丢失,且无法自动恢复
  • 发布者若向 Master 的 channel 发布消息,该消息**不会转发给 Slave 上的订阅者**——Pub/Sub 不走复制通道,它是独立于 RDB/AOF 的实时通信路径
  • 你看到的 “订阅成功” 只是 Redis 允许注册,不代表它能稳定收消息;真实场景中,99% 的生产环境都禁止把业务订阅逻辑部署在 Slave 上

读写分离架构下正确的发布/订阅部署方式

Pub/Sub 本质是实时广播通道,不是持久化消息队列。它必须和写入口对齐,否则语义就断了。正确做法只有一个:所有 PUBLISH 和关键 SUBSCRIBE 都走 Master 节点(或明确的写节点)。

  • 发布端必须连 Master —— 否则消息发不出去,或只发到局部节点
  • 订阅端可连 Master 或 Sentinel/Cluster 中的任意可读节点,但需确保:连接的是同一个逻辑集群,且网络可达 Master(因为 Pub/Sub 消息不复制,订阅者必须直连消息源)
  • 如果用了代理(如 HAProxy、Twemproxy、Redis Proxy),确认它支持 Pub/Sub 协议透传;很多代理默认截断或不转发 SUBSCRIBE 流,导致“看似连上了,实则收不到”
  • 使用客户端库(如 Jedis、StackExchange.Redis)时,检查是否启用了 pubsub 专用连接池——普通连接池可能复用连接,而 SUBSCRIBE 后连接进入监听态,不能再发其他命令

容易被忽略的兼容性细节

有些团队试图绕过限制,在 Slave 上用 CONFIG SET replica-read-only no 再 PUBLISH,结果发现消息确实发出去了,但很快引发连锁问题:

  • 该 Slave 的复制偏移量(master_repl_offset)不再与 Master 对齐,INFO replication 显示 repl_backlog_active:0 或同步中断
  • 其他 Slave 可能因收到不一致的复制流而报错 Replication stream corrupted
  • 哨兵(Sentinel)或 Cluster 会检测到该节点状态异常,可能触发误判或自动剔除
  • 更隐蔽的问题:某些客户端(尤其是老版本)在收到 READONLY 错误后会静默降级重试,但重试目标仍是同一 Slave,形成死循环

真正需要读写分离 + Pub/Sub 的场景,应该用独立的 Master 实例承载发布逻辑,而不是强行在 Slave 上开写权限。

相关专题

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

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

2023.11.02

4349

19

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

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

2023.11.14

3855

11

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

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

2024.04.02

7032

6

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

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

2024.04.07

623

6

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

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

2024.04.07

756

6

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

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

2024.04.07

6742

6

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

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

2024.04.07

1160

6

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

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

2024.04.07

1036

6

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

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

2024.04.07

5958

6

热门下载

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

精品课程

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

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习