应用写Redis时突然返回 READONLY You can't write against a read only replica,核心含义不是磁盘只读,而是当前连接的Redis节点身份是副本。Redis从2.6开始默认让副本拒绝写命令,避免客户端误把数据写到复制链的错误一侧。
正确做法是恢复写客户端到主节点的路由,或按高可用流程完成副本提升。 把副本改成可写会制造只存在于本机的数据,重新同步或重启后可能丢失。

先确认当前连接的是主节点还是副本
在应用使用的同一主机和端口上检查角色:
redis-cli -h 127.0.0.1 -p 6379 ROLE
redis-cli -h 127.0.0.1 -p 6379 INFO replication
ROLE 第一项返回master才是普通写入目标;返回slave或replica,INFO replication 中也会看到 role:slave,并列出上游地址、连接状态和复制偏移。
托管Redis、Sentinel或Cluster环境还要核对客户端实际解析的域名、服务发现结果和连接池里的旧地址。只在服务器上查询默认6379,可能与应用真正访问的端点不同。
必须用应用的真实端点确认角色,不能只根据机器名称推断主从。
修正连接地址和服务发现
主节点仍健康时,把应用写连接改回主节点、primary endpoint或Sentinel返回的当前master。修改后应清理或重建旧连接池,否则进程可能继续复用已经指向副本的TCP连接。
redis-cli -h PRIMARY_HOST -p 6379 ROLE
redis-cli -h PRIMARY_HOST -p 6379 SET vps911:write-test ok EX 60
测试键应使用明确前缀和较短TTL,避免污染业务数据。Redis Cluster客户端应启用集群拓扑发现与重定向处理,不能把普通单节点客户端固定到某个replica地址。
修复连接配置后还要重建连接池并检查DNS缓存。 配置文件改对但旧连接未释放,READONLY仍可能持续出现。
不要把replica-read-only改成no
Redis官方说明,replica-read-only 默认开启。虽然可以通过配置把副本改成可写,但可写副本只为历史兼容保留,官方不建议使用,因为主节点的复制流可能与本地写入产生不一致。
副本重新同步时,主节点数据会覆盖副本数据;副本上的本地写入也不会按正常主从语义传播给下游。即使短时间内命令成功,也不能把它当作可靠修复。
不要执行 @@HTMLTOKEN0@@ 让报错消失。 这只是取消保护,既没有修复主节点路由,也没有建立安全的新主节点。
主节点故障时按高可用流程切换
使用Sentinel或托管高可用服务时,应先确认自动故障转移状态、仲裁和新主节点,再让应用重新发现端点。手工环境确实需要提升副本时,Redis提供:
redis-cli -h NEW_PRIMARY -p 6379 REPLICAOF NO ONE
redis-cli -h NEW_PRIMARY -p 6379 ROLE
该命令会停止复制并把实例转为master,同时保留当前已经复制的数据,但它属于拓扑变更。执行前要确认旧主节点已隔离,避免网络分区下出现两个可写主节点。
需要演练切换时,可在 萤光云 建立隔离的主从环境;想验证异地客户端重连,可用 LightNode 部署按小时测试机。演练不要使用生产RDB、AOF或真实密码。
检查为什么应用会连到副本
常见根因包括把读写端点写反、DNS或代理仍指向旧主节点、故障转移后连接池未刷新、负载均衡把写请求分发到全部节点,以及人工维护后没有恢复服务发现。
应对照故障时间查看应用、Sentinel、代理和Redis日志,并检查部署变量里是否同时存在读端点与写端点。只修一台应用服务器可能留下其他实例继续向副本写入。
最终修复点通常在客户端路由或高可用发现层,而不是副本的只读开关。
写入恢复后的验收标准
先确认目标节点角色,再执行带TTL的测试写入和读取;随后观察应用错误率、复制状态与主从偏移:
redis-cli -h PRIMARY_HOST -p 6379 ROLE
redis-cli -h PRIMARY_HOST -p 6379 SET vps911:write-test ok EX 60
redis-cli -h PRIMARY_HOST -p 6379 GET vps911:write-test
redis-cli -h REPLICA_HOST -p 6379 INFO replication
旧主节点恢复上线前,应明确它作为副本重新加入,而不是继续接受写入。托管服务则以控制台或官方API显示的primary状态为准。
验收通过应同时满足写请求全部命中master、READONLY错误归零、副本复制连接正常,并且下一次故障转移后客户端能自动更新拓扑。
FAQ
重启Redis能解决READONLY吗?
不能保证。节点重启后仍是副本,或应用仍连错地址,错误会继续出现,还可能引入额外停机。
副本能不能只承担查询?
可以,但读取可能存在复制延迟。应用必须把读写连接分开,并接受副本读到稍旧数据的可能性。
执行REPLICAOF NO ONE会删除现有数据吗?
该形式会停止复制并保留当前数据,但会改变拓扑。必须先隔离旧主节点并按故障切换流程执行。
温馨提示
READONLY是保护机制,不是需要绕过的限制。先找回唯一写主节点,再恢复客户端路由;任何手工提升都要防止双主并保留可回退的拓扑记录。


