Spring Boot集成Redis哨兵模式需配置sentinel节点及master名称,由Lettuce自动发现主节点并支持读写分离;读操作可设ReadFrom.REPLICA_PREFERRED优先从从节点读取,写操作始终路由至主节点,确保高可用与负载均衡。

直接结论:客户端必须明确区分读写路径,不能靠“连上就写”——否则90%的ReadOnlyError都源于它误连从节点或未启用哨兵/集群自动发现机制。
怎么确认客户端连的是主节点还是从节点?
别猜,用INFO REPLICATION看真实角色。在连接当前Redis实例后执行:
redis-cli -h <host> -p <port> INFO REPLICATION | grep role
输出role:master才安全;若为role:slave,说明客户端配置或代理层已把写请求打到了从节点。
- Spring Boot + Lettuce 场景下,可加日志开关:
logging.level.io.lettuce.core=DEBUG,观察连接初始化时打印的master地址是否匹配预期 - Docker 或 K8s 环境中,检查服务发现配置(如
redis-sentinelService 是否被误指向某个redis-slavePod) - 如果用
redis-cli手动连都能复现错误,基本排除代码逻辑问题,聚焦网络/配置层
Spring Boot 项目里 RedisTemplate 怎么强制走主节点?
关键不是“让从节点变可写”,而是让客户端知道哪是主——尤其当用了哨兵或集群时,RedisTemplate本身不自动识别主从拓扑,全靠RedisConnectionFactory提供正确连接源。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 哨兵模式下,必须用
RedisSentinelConfiguration,且master名称要和哨兵监控的主节点别名完全一致(比如哨兵配置里是mymaster,代码里就不能写master) - 集群模式下,连接字符串必须是多个节点地址(如
redis://10.0.1.10:6379,redis://10.0.1.11:6379),不能只填一个;Lettuce 会自动发现主从关系并路由写请求 - 如果硬编码了单个
spring.redis.host和port,那等于绕过所有高可用机制,一旦该节点是副本或故障切换后降级,立刻报READONLY
为什么改了slave-read-only no还是报错?
这个配置只影响“该节点是否允许写”,但不解决“客户端该不该写它”的设计问题。强行放开只读限制,等于让从节点承担主节点职责,破坏复制一致性,且无法应对后续故障转移。
-
slave-read-only no是运行时可调参数,但Docker容器重启后会丢失,除非挂载了持久化redis.conf并显式写入该行 - 某些云Redis服务(如阿里云、腾讯云)禁止修改
slave-read-only,控制台操作无效,改了也白改 - 即使设为
no,从节点仍可能因复制延迟、网络分区等原因拒绝写入,错误变成NOAUTH或LOADING而非READONLY,排查更隐蔽
Lettuce 客户端连接池要不要配readFrom?
要,而且必须配对。默认readFrom = ReadFrom.MASTER,但如果你的应用有读多写少场景,想把读请求分摊到从节点,就得显式声明策略,否则所有命令(包括GET)都走主节点,浪费资源。
- 读写分离场景:设
readFrom = ReadFrom.REPLICA_PREFERRED,写仍走主,读优先从副本负载 - 强一致性要求:保持
ReadFrom.MASTER,避免读到旧数据 - 注意:Lettuce 的
readFrom只对读命令生效,SETINCR等写命令永远发往主节点——前提是连接工厂已正确识别主节点
最常被忽略的一点:客户端版本太老。Lettuce 5.3+ 才完整支持 Redis 6 的 ACL 和哨兵自动故障转移感知,低版本遇到主从切换后,可能缓存旧主地址长达数分钟。升级前先查io.lettuce.core.RedisClient初始化日志里有没有Discovered master字样。

















