根本原因是写请求发到了只读从库,而非同步问题;确认方法:用redis-cli INFO replication查role字段,若为slave且CONFIG GET replica-read-only返回yes,则确为只读从库拦截。

Redis 主从同步中出现 READONLY 错误,根本原因不是“同步出问题”,而是写请求发到了只读从节点上——slave-read-only(或 replica-read-only)配置只是暴露了这个路由错误。
怎么确认当前连接的 Redis 节点是不是只读从库
别猜,直接查运行时状态:
- 用
redis-cli -h your_ip -p 6379 INFO replication查看role字段:若返回role:slave,说明你连的就是从库 - 再执行
CONFIG GET replica-read-only(Redis 5.0+)或CONFIG GET slave-read-only(旧版),确认值是否为"yes" - 用非本地地址连接(如
redis-cli -h 192.168.1.10 -p 6379)试一个SET test 1:如果返回(error) READONLY You can't write against a read only replica.,就坐实了是只读从库拦截
为什么设了 slave-read-only yes 还会报错
这个配置本身没问题,但容易被以下情况绕过或掩盖:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 配置文件里写了
slave-read-only yes,但进程启动时加载的是另一份配置(比如容器挂载路径错误、--config指向了空文件) - 运行时被手动执行过
CONFIG SET replica-read-only no,而你没在配置文件里同步改掉,重启后又变回yes,导致环境不一致 - 用了云数据库代理(如阿里云 Proxy 模式、腾讯云 CRS),它把你的写请求转发到了后端只读副本,此时改本地
replica-read-only完全无效 - 客户端 SDK 或连接池缓存了旧连接,实际连的是故障转移前的主节点(现在已降级为从节点),
INFO replication显示role:slave就是铁证
CONFIG SET replica-read-only no 看似生效,但为什么不能随便开
临时关闭只读模式确实能让 SET 成功,但这不是修复,是埋雷:
- 写入的数据不会同步回主库,主库宕机后若该从库被提升为主库,脏数据就变成合法数据
- 其他从库重新同步时会拉取这个错误状态,扩散不一致
- 某些 ACL 配置下,管理员用户(如
default用户带+@all)仍可绕过replica-read-only,但普通业务用户不行——权限和只读开关是两套机制 - Redis Cluster 场景下该配置完全不生效,
CLUSTER REPLICATE控制的从节点默认拒绝写入,硬编码逻辑,改replica-read-only没用
最常被忽略的排查盲区:连接地址本身就不对
你以为填的是主库地址,其实连上的早就是从库了:
- DNS 或 hosts 文件把主库域名解析到了从库 IP(尤其滚动升级后未清理缓存)
- 公司内网负载均衡器做了静默转发,比如把所有
:6379请求轮询到主+从节点组 - 哨兵(Sentinel)切换后,客户端没及时更新
SENTINEL get-master-addr-by-name结果,还在往旧地址发请求 - Navicat 类工具显示 READONLY,本质是协议不兼容,它根本没连上 Redis,更不是节点只读的问题——换
redis-cli ping一试便知
真正关键的不是调哪个参数,而是让写请求准确落到主节点上。配置开关只是最后一道防线,不是路由策略。

















