必须显式配置 read-from,否则所有读操作默认打到主节点;哨兵模式下需配置 spring.redis.sentinel.nodes 和 master,并将 read-from 置于 spring.redis.lettuce 下设为 replica_preferred(lettuce 5.2+)或 slave_preferred(旧版),且主从序列化器必须一致。

必须显式配置 read-from,否则所有读操作(包括 @Cacheable、redisTemplate.opsForValue().get()、hasKey())默认全部打到主节点——从节点零负载,主节点连接数和延迟持续升高。
application.yml 中正确配置 REPLICA_PREFERRED
这是生产环境最稳妥的选择:优先读从节点,任一从节点可用即路由过去;所有从节点均不可用时,自动降级读主节点,保障可用性。
-
read-from必须写在spring.redis.lettuce下,不是spring.redis根层级,也不是spring.redis.lettuce.cluster(集群模式专用) - 哨兵模式下,
spring.redis.sentinel.nodes和spring.redis.sentinel.master必须完整配置,否则 Lettuce 无法识别主从拓扑,REPLICA_PREFERRED形同虚设 - 拼写和大小写敏感:
REPLICA_PREFERRED(Lettuce 5.2+),旧版本(如 Spring Boot 2.1.5 自带的 Lettuce 5.1.x)需用SLAVE_PREFERRED,直接照抄高版本配置会编译报错 - 示例(哨兵模式):
spring:
redis:
sentinel:
nodes: 192.168.1.10:26379,192.168.1.11:26379
master: mymaster
lettuce:
pool:
max-active: 32
read-from: REPLICA_PREFERRED
为什么单靠 spring.redis.host + port 无法触发读写分离
Lettuce 把 spring.redis.host:port 当作单节点直连地址,即使你填了多个用逗号分隔(如 192.168.1.10:6379,192.168.1.11:6379),它也只视其为故障转移候选列表,不会主动发现主从关系。没有哨兵或集群拓扑信息,read-from 策略根本无从生效。
- 主从直连场景下,必须用
RedisStaticMasterReplicaConfiguration手动指定主节点 + 所有从节点地址,再构建LettuceConnectionFactory - 集群模式下,
spring.redis.cluster.nodes必须包含主+所有从节点,且read-from配置位置与哨兵不同:要放在spring.redis.lettuce.cluster下 - 无论哪种模式,
read-from都是运行时动态决策——每次调用sync()或async()时才根据当前节点健康状态选节点,不是连接建立时就固定
自定义 LettuceConnectionFactory 实现运行时策略切换
当需要按业务维度(如请求头 X-Region: shenzhen)、流量比例或灰度开关动态控制读副本行为时,静态 yml 配置不够用,必须代码干预客户端构建过程。
- 实现
LettuceClientConfigurationBuilderCustomizer接口,在customize()方法中根据条件调用builder.readFrom(ReadFrom.REPLICA_PREFERRED)或ReadFrom.MASTER - 注意:该定制器对所有
RedisTemplate、@Cacheable、ReactiveRedisTemplate全局生效,不能只影响某一个模板实例 - 若需更细粒度控制(比如部分方法走从库、部分强一致读必须走主库),应注册两个独立的
LettuceConnectionFactory(一个配MASTER,一个配REPLICA_PREFERRED),再分别注入不同命名的RedisTemplate,由业务代码显式选择
最容易被忽略的一点:read-from 策略对序列化器无感知,但如果你的主从节点使用了不兼容的序列化方式(比如主库用 JdkSerializationRedisSerializer,从库用 StringRedisSerializer),读操作会抛出反序列化异常——务必保证副本连接工厂与主连接工厂使用完全一致的 RedisTemplate 序列化配置。











