彻底解决 RedisReadOnlyException:从「只读从节点」到「独立主节点」的实战指南
在 Spring Boot 项目集成 Redis 时,很多开发者都会遇到 io.lettuce.core.RedisReadOnlyException: READONLY You can't write against a read only replica. 这个异常。看似简单的「写入被拒绝」,背后却涉及 Redis 主从架构的核心逻辑。本文将结合实际操作场景,从异常分析、问题排查到最终落地解决方案,一步步带你彻底解决这个问题,甚至将原本的只读从节点改造为独立可读写的主节点。
一、异常背景与现场还原
1. 异常现象
Spring Boot 项目启动失败,抛出核心异常:
plaintext
org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisReadOnlyException: READONLY You can't write against a read only replica.
从异常堆栈可以清晰看到,项目在执行 RedisCache.setCacheObject() 写入操作时被拒绝,根源是连接的 Redis 节点为「只读副本」(从节点)。

2. 前期操作现场还原
为了排查问题,我们在 Windows 终端尝试连接 Redis 服务器,成功连接 Redis 节点,并通过 INFO replication 命令排查节点信息:
运行
C:\Users\admin>redis-cli -h xxx.xx.121.134 -p 6379
xxx.xx.121.134:6379> INFO replication
返回结果暴露了核心问题,关键信息提炼如下:
| 配置项 | 取值 | 含义解读 |
|---|---|---|
role |
slave |
当前连接的是 Redis 从节点(只读副本) |
master_host |
xxx.xx.232.83 |
对应的主节点 IP 地址 |
master_port |
25154 |
对应的主节点端口(非默认 6379) |
master_link_status |
down |
从节点与主节点连接已断开,无法同步数据 |
slave_read_only |
1 |
从节点只读模式开启(1 = 开启,0 = 关闭) |
connected_slaves |
0 |
无下级从节点,当前节点为最末端副本 |
二、异常核心原理解析
要解决这个异常,首先要理解 Redis 主从复制架构的核心设计:
-
主节点(Master) :具备「读写权限」,负责接收所有写操作(
SET、HSET等),同时将数据同步到所有从节点,是整个架构的核心数据节点。 -
从节点(Slave/Replica)
:默认「只读权限」(
slave-read-only yes),仅能执行读操作(
GET、
HGET等),无法执行写操作,其核心作用是:
- 分担主节点的读压力,提高查询性能;
- 作为主节点的备份,当主节点故障时可快速切换,保障高可用;
- 避免直接对主节点执行大量读操作,防止主节点过载。
-
只读模式的意义:从节点的只读模式是 Redis 的默认配置,目的是保障主从数据一致性。如果允许从节点写入,会导致从节点数据与主节点不一致,同步时出现冲突,最终引发整个架构的数据混乱。
本次异常的本质就是:Spring Boot 项目向一个处于「只读模式」的 Redis 从节点执行了写操作,被 Redis 按照默认规则拒绝,从而抛出 RedisReadOnlyException。
更关键的是,本次场景中的从节点与主节点连接已断开(master_link_status:down),即使想同步数据也无法实现,此时的从节点只是一个「孤立的只读副本」,无法满足项目的读写需求。
三种解决方案(从临时应急到长期优化)
针对本次场景,我们提供三种解决方案,分别适用于「临时应急」「快速落地」「长期优化」三种场景,其中重点讲解「将从节点改造为独立主节点」的实战操作(也是本次现场操作的核心方案)。
方案一:临时应急 ------ 关闭从节点只读模式(快速解决写入问题)
该方案适用于「主节点无法快速修复,项目需要紧急启动」的场景,仅需关闭当前从节点的只读模式,即可让其支持写操作。
1. 核心操作命令
连接 Redis 从节点后,执行以下命令关闭只读模式:
运行
# 关闭从节点只读模式(临时生效,Redis 重启后失效)
xxx.xx.121.134:6379> CONFIG SET slave-read-only no
OK
2. 验证效果
执行完命令后,可通过以下方式验证只读模式是否关闭:运行
# 查看只读模式配置
xxx.xx.121.134:6379> CONFIG GET slave-read-only
1) "slave-read-only"
2) "0" # 返回 0 表示只读模式已关闭(1 表示开启)
此时,再通过 Spring Boot 项目执行写操作,即可成功执行,异常消失。
3. 优缺点与注意事项
- 优点:操作简单、快速生效,无需修改项目配置,无需搭建新节点;
- 缺点:
- 临时生效,Redis 重启后只读模式会恢复默认开启状态;
- 从节点与主节点连接已断开,改造后的数据无法同步到原主节点,若后续恢复主从连接,可能引发数据冲突;
- 无持久化配置的情况下,Redis 重启后数据会丢失;
- 适用场景:紧急测试、项目临时启动、无需长期保留数据的场景;
- 注意:生产环境严禁单独使用该方案,仅可作为应急过渡手段。

方案二:实战核心 ------ 将从节点改造为独立主节点(长期可用)
该方案是本次现场操作的核心,通过 SLAVEOF NO ONE 命令,将原本的「只读从节点」脱离主从架构,改造为「独立主节点」,具备完整的读写权限,且长期有效(即使 Redis 重启,也不会恢复为从节点)。
1. 核心操作步骤(全程实战可复现)
步骤 1:连接 Redis 从节点(同前文)
运行
C:\Users\admin>redis-cli -h xxx.xx.121.134 -p 6379
步骤 2:脱离主从架构,升级为独立主节点
执行 SLAVEOF NO ONE 命令,让当前从节点与原主节点断开连接,成为独立主节点:
bash
xxx.xx.121.134:6379> SLAVEOF NO ONE
OK
步骤 3:关闭只读模式,开启读写权限
bash
xxx.xx.121.134:6379> CONFIG SET slave-read-only no
OK
步骤 4:验证改造结果
执行 INFO replication 命令,查看节点角色是否已变更:
bash
xxx.xx.121.134:6379> INFO replication
# Replication
role:master # 节点角色已从 slave 变为 master,说明升级成功
connected_slaves:0 # 无下级从节点,当前为独立主节点
master_failover_state:no-failover
master_replid:dc0281a4f7cfe69b0ad5459a5a540105eab3cb8e
master_replid2:c35f038e051be82e906b905e1dfa47b87df774c7
master_repl_offset:0
second_repl_offset:1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
步骤 5:验证读写功能(可选,确保改造有效)
运行
# 执行写操作
xxx.xx.121.134:6379> SET test_key "spring_boot_redis_test"
OK
# 执行读操作
xxx.xx.121.134:6379> GET test_key
"spring_boot_redis_test"
# 删除测试数据(可选)
xxx.xx.121.134:6379> DEL test_key
(integer) 1
2. 额外问题处理:CONFIG REWRITE 报错
本次操作中,执行 CONFIG REWRITE 命令时出现报错:
bash 运行
xxx.xx.121.134:6379> CONFIG REWRITE
(error) ERR The server is running without a config file
报错原因
CONFIG REWRITE 命令的作用是将当前的运行时配置写入 Redis 配置文件(redis.conf),实现配置持久化。本次报错是因为 Redis 启动时未指定配置文件,以「无配置文件模式」运行,无法写入配置。
解决方案
-
若无需持久化配置:可忽略该报错,当前的「主节点身份」和「关闭只读模式」的配置在 Redis 运行期间有效,仅需注意 Redis 重启后需重新执行命令(或指定配置文件启动);
-
若需要持久化配置:
-
停止当前 Redis 进程:
pkill redis-server; -
创建或编辑
redis.conf配置文件,添加以下配置:
conf
# 配置为独立主节点(无需连接其他主节点) # slaveof xxx.xx.232.83 25154 (注释掉原有主从配置) # 关闭只读模式,支持读写 slave-read-only no # 其他必要配置(端口、绑定IP等) port 6379 bind 0.0.0.0 protected-mode no -
以配置文件启动 Redis:
redis-server /usr/local/redis/conf/redis.conf(替换为你的配置文件路径); -
再次执行
CONFIG REWRITE,即可成功将配置写入文件。
-
3. 优缺点与注意事项
-
优点:
- 操作简单,无需搭建新节点,充分利用现有资源;
- 改造后为独立主节点,支持完整读写权限,长期可用;
- 无需修改 Spring Boot 项目配置,直接复用原有连接信息;
-
缺点:
- 原主节点的数据无法同步到当前节点(因原主从连接已断开),可能存在数据丢失;
- 改造后的节点为单机模式,无高可用保障,若节点故障,项目将无法使用 Redis;
-
适用场景:原主节点无法修复、项目需要长期使用 Redis、对高可用要求不高的场景(如中小型项目、测试环境);
-
注意:生产环境中,改造后建议配置 Redis 持久化(RDB/AOF),防止数据丢失,同时可搭建新的主从架构,保障高可用。
方案三:长期优化 ------ 连接原主节点 / 搭建新主从架构(生产环境推荐)
该方案适用于「对数据一致性和高可用要求较高」的生产环境,核心思路是「回归标准主从架构」,避免单机节点的故障风险。
1. 子方案 3.1:修复并连接原主节点
-
核心操作:
-
排查原主节点
xxx.xx.232.83:25154的故障原因(如端口是否放行、Redis 是否启动、配置是否正确); -
修复原主节点故障,确保其正常运行且支持读写操作;
-
修改 Spring Boot 项目
application.yml配置,指向原主节点:
yaml
spring: redis: host: xxx.xx.232.83 # 原主节点 IP port: 25154 # 原主节点端口 password: '' # 原主节点密码(如有) timeout: 300s lettuce: pool: min-idle: 0 max-idle: 8 max-active: 8 max-wait: -1ms -
重启 Spring Boot 项目,验证读写功能正常。
-
-
优点:保留原有数据架构,数据一致性有保障;
-
缺点:排查和修复原主节点故障耗时较长。
2. 子方案 3.2:搭建新的 Redis 主从架构
-
核心操作:
- 搭建新的 Redis 主节点(支持读写)和从节点(只读,分担读压力);
- 配置主从同步,确保从节点能正常同步主节点数据;
- 修改 Spring Boot 项目配置,指向新主节点,同时可集成 Redisson 等框架实现读写分离;
- 迁移原有数据到新主节点,确保数据不丢失。
-
优点:高可用保障,读写分离提升性能,适合大规模生产环境;
-
缺点:搭建和配置复杂,耗时较长,需要一定的运维经验。
3. 适用场景
生产环境、对数据一致性和高可用要求较高的项目、大规模分布式系统。
四、Spring Boot 项目验证与后续优化
1. 项目验证步骤
无论采用哪种方案,解决后都需要通过以下步骤验证项目是否正常:
- 启动 Spring Boot 项目 :观察日志,确保无
RedisReadOnlyException和RedisConnectionException异常,相关 Bean(如sysConfigServiceImpl)初始化成功; - 验证写操作:触发项目中的 Redis 写操作(如更新系统配置、缓存用户信息);
- 验证读操作:查询已写入的缓存数据,确保能正常读取;
- 验证数据持久化(可选):重启 Redis 后,查看缓存数据是否存在,确保数据不会丢失。
2. 后续优化建议
- 配置 Redis 持久化:生产环境中,建议开启 RDB 和 AOF 混合持久化,既保障数据安全性,又兼顾性能;
- 设置 Redis 密码 :避免未授权访问,提高安全性,配置项
requirepass; - 限制连接 IP :通过
bind配置项限制允许连接的 IP,避免恶意访问; - 监控 Redis 状态 :使用 Redis 自带的
INFO命令或第三方监控工具(如 Prometheus + Grafana),实时监控 Redis 的运行状态、内存使用、连接数等指标; - 实现读写分离:生产环境中,通过 Redisson 等框架实现读写分离,写操作指向主节点,读操作指向从节点,提升项目性能。
五、总结
RedisReadOnlyException的核心原因是「向 Redis 从节点执行写操作」,从节点默认只读模式拒绝写请求;- 排查问题的关键是使用
INFO replication命令查看 Redis 节点角色,确认是否为从节点; - 三种解决方案各有适用场景:临时应急可关闭只读模式,快速落地可将从节点改造为独立主节点,生产环境推荐搭建标准主从架构;
SLAVEOF NO ONE是将从节点改造为独立主节点的核心命令,配合CONFIG SET slave-read-only no可实现完整读写权限;- 实现读写分离:生产环境中,通过 Redisson 等框架实现读写分离,写操作指向主节点,读操作指向从节点,提升项目性能。