根本原因是客户端未及时切换至新主节点地址,仍在向已降级为从节点的旧主发写请求;需检查连接配置、DNS/服务发现缓存、客户端角色感知能力及代理路由规则,并确认新主节点已显式关闭slave-read-only限制。

执行 SLAVEOF NO ONE 后仍报 ReadOnlyError
根本原因不是命令没生效,而是客户端仍在往旧地址发请求——那个“刚升主”的节点,可能压根没被客户端连上。常见现象是 redis.exceptions.ReadOnlyError 持续出现,但 INFO replication 显示 role:master,说明角色切换成功,只是流量没切过去。
排查要点:
- 检查客户端连接字符串:是否还指向原主节点(此时已降级为从节点),而非新主节点的 IP 和端口
- 确认 DNS 或服务发现缓存未过期:Kubernetes 中的 headless service、Consul/Nacos 注册信息可能延迟更新
- 验证客户端是否支持自动重连 + 角色感知:Jedis 默认不自动识别角色变更;Lettuce 在启用
DynamicNodeResolver且配合 Sentinel 时才可靠,纯主从下需手动刷新连接 - 代理层(如 Twemproxy、Redis Exporter)未重载路由规则,仍将写请求打到旧主节点
SLAVEOF NO ONE 执行后 role 是 master,但 SET 仍失败
这通常意味着节点虽已脱离复制,但配置层面仍残留只读限制。Redis 不会因 SLAVEOF NO ONE 自动开启写权限,它只改角色和断连接,其他行为由配置项控制。
必须检查并显式关闭只读模式:
- 运行时临时修复:
CONFIG SET slave-read-only no(注意:该设置重启失效) - 持久化修复:编辑
redis.conf,将slave-read-only yes改为no,然后重启或CONFIG REWRITE - 特别注意:若使用
redis-server --slaveof no one启动,该参数不会覆盖配置文件中的slave-read-only,仍以配置为准
新主节点接收写入后,其他从节点无法自动跟上
SLAVEOF NO ONE 只影响当前节点,不会触发集群拓扑广播。其他从节点仍连着旧主(或已失联),不会自发转向新主。
必须人工干预或脚本驱动:
- 在每个待同步的从节点上执行:
SLAVEOF 新主IP 新主端口 - 若旧主已不可达,从节点会报
Connection refused或卡在connecting状态,需先SLAVEOF NO ONE清理旧状态,再SLAVEOF新主 - 配置文件中若硬编码了
slaveof,重启后会自动回退——务必删掉或注释掉该行,否则CONFIG REWRITE可能将其恢复 - 生产环境强烈建议用 Sentinel 管理切换,避免此类手动链式操作出错
为什么 INFO replication 显示 master,但 WAIT 命令返回 0?
WAIT 的行为依赖当前连接所连节点的复制拓扑视图。SLAVEOF NO ONE 后,该节点不再有从节点,所以 WAIT 1 1000 必然返回 0——不是 bug,是预期行为。
这意味着:
-
WAIT在手动提升场景下完全失效,不能用于验证数据安全落地 - 若业务强依赖写入同步保障,应提前配置
min-slaves-to-write和min-slaves-max-lag,而不是寄希望于故障后补救 - 新主节点若需立即承担写流量,必须确保它已作为主节点被其他节点正确识别并建立复制关系,否则它的“主”只是孤岛式的
最易被忽略的一点:SLAVEOF NO ONE 不改变任何配置文件内容,也不触发 CONFIG REWRITE。一次运维操作后如果忘记清理 slaveof 配置项或 slave-read-only yes,下次重启就退回从节点,且继续只读——这种“静默回滚”比当场失败更难排查。











