Spring Data Redis 主从集群 哨兵集群 分片集群 yml 配置
Spring Data Redisyml 配置中添加 Redis 主从集群配置一主二从集群没有哨兵在 Spring Data Redis 中针对没有哨兵Sentinel的一主二从架构配置方式主要取决于你使用的客户端Lettuce 或 Jedis以及你是否需要读写分离。通常情况下Spring Boot 会自动发现主从关系但如果需要精细控制如强制从从节点读取则需要通过 Java 配置类配合yml来实现。以下是基于Lettuce客户端Spring Boot 2.x/3.x 默认的完整配置方案。1.application.yml配置在没有哨兵的情况下我们通常手动指定所有节点主节点 从节点或者仅指定主节点Lettuce 会自动通过CLUSTER NODES或INFO REPLICATION发现从节点但在静态主从模式下建议显式列出。spring:redis:# 默认连接的主节点 IP用于初始化连接host:192.168.1.100port:6379password:your_passworddatabase:0timeout:3000ms# 关键配置Lettuce 连接池与读写策略lettuce:pool:max-active:20# 最大连接数max-idle:10# 最大空闲连接min-idle:5# 最小空闲连接max-wait:2000ms# 连接超时时间# 拓扑刷新策略可选用于动态感知节点变化cluster:refresh:adaptive:true# 如果你使用的是 Jedis配置结构会有所不同见下文补充jedis:pool:max-active:20max-idle:10min-idle:5注意在纯主从模式非集群模式下spring.redis.cluster.nodes配置项通常不生效或不需要配置。我们需要在 Java 配置类中构建静态的主从拓扑。2. Java 配置类实现读写分离仅靠 yml 配置Spring 默认所有请求都会发往主节点。为了实现**“主写从读”**你需要创建一个配置类利用LettuceClientConfiguration设置读取策略。这里演示如何配置优先从从节点读取(REPLICA_PREFERRED)importio.lettuce.core.ReadFrom;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.RedisPassword;importorg.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;importorg.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;importorg.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;importorg.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;importjava.util.Arrays;ConfigurationpublicclassRedisMasterReplicaConfig{Value(${spring.redis.host})privateStringhost;Value(${spring.redis.port})privateintport;Value(${spring.redis.password})privateStringpassword;BeanpublicLettuceConnectionFactoryredisConnectionFactory(){// 1. 定义主从节点拓扑结构// 格式host:port这里手动指定一主二从RedisStaticMasterReplicaConfigurationconfignewRedisStaticMasterReplicaConfiguration(Arrays.asList(host:port,// 主节点192.168.1.101:6380,// 从节点 1192.168.1.102:6381// 从节点 2));config.setPassword(RedisPassword.of(password));// 2. 配置 Lettuce 客户端行为LettuceClientConfigurationclientConfigLettucePoolingClientConfiguration.builder()// 核心配置优先从从节点读取数据// 如果从节点不可用会自动回退到主节点.readFrom(ReadFrom.REPLICA_PREFERRED).build();// 3. 创建连接工厂returnnewLettuceConnectionFactory(config,clientConfig);}}3. 核心配置说明配置项/策略说明RedisStaticMasterReplicaConfiguration用于在非哨兵模式下手动指定主从节点列表。Spring 会维护这个静态列表。ReadFrom.REPLICA_PREFERRED推荐。优先从 Slave 读取如果 Slave 挂了自动切回 Master保证高可用。ReadFrom.REPLICA强制只从 Slave 读取。如果 Slave 全挂会抛出异常不推荐除非你有严格的一致性要求且能容忍报错。ReadFrom.UPSTREAM默认行为。只从 Master 读取即没有读写分离。4. 补充如果你使用的是 Jedis虽然 Lettuce 是默认推荐但如果你使用的是 Jedis配置逻辑类似但类名不同// Jedis 版本的配置思路importorg.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;importorg.springframework.data.redis.connection.jedis.JedisClientConfiguration;importorg.springframework.data.redis.connection.jedis.JedisConnectionFactory;// ... 在 Bean 中RedisStaticMasterReplicaConfigurationconfignewRedisStaticMasterReplicaConfiguration(...);// Jedis 同样支持 readFrom 设置但通常通过 JedisClientConfiguration 构建JedisClientConfigurationclientConfigJedisClientConfiguration.builder().readFrom(ReadFrom.REPLICA_PREFERRED).build();returnnewJedisConnectionFactory(config,clientConfig);5. 验证配置是否生效启动项目后你可以通过以下方式验证查看日志启动时观察控制台日志看是否成功连接到了所有指定的节点。压测观察在主节点和从节点的服务器上使用tcpdump或 Redis 监控工具观察GET请求是否分发到了从节点6380, 6381而SET请求是否只在主节点6379执行。Redis 命令在 Redis 主节点执行info replication确保connected_slaves数量为 2且状态为online。Spring Data Redisyml 配置中添加 Redis 哨兵集群配置在 Spring Data Redis 中配置Redis 哨兵Sentinel集群核心在于告诉 Spring Boot“不要直接连 Redis 主节点而是去问哨兵节点当前的老大Master是谁”。以下是基于Spring Boot 2.x/3.x和默认客户端Lettuce的完整配置方案。1.application.yml配置这是最关键的一步。你需要配置哨兵节点的列表以及主节点在哨兵配置中定义的逻辑名称通常叫mymaster但具体取决于你的 Redis 服务端配置。spring:redis:# 1. 哨兵配置核心sentinel:master:mymaster# 【重要】这是 Redis 主节点在 Sentinel 配置中的逻辑名称不是 IPnodes:# 哨兵节点的 IP:Port 列表建议配置所有哨兵用逗号分隔或列表格式-192.168.1.100:26379-192.168.1.101:26379-192.168.1.102:26379# 2. 认证与基础配置password:your_redis_password# Redis 主从节点的密码# sentinel-password: your_sentinel_password # 如果哨兵节点单独设置了密码需配置此项Spring Boot 2.4database:0timeout:3000ms# 3. 连接池配置 (Lettuce)lettuce:pool:max-active:20# 最大连接数max-idle:10# 最大空闲连接min-idle:5# 最小空闲连接max-wait:2000ms# 获取连接的最大等待时间⚠️ 注意事项master字段必须与 Redis 服务端sentinel.conf中sentinel monitor master-name ...这一行的master-name完全一致。nodes字段这里填写的是哨兵的端口默认 26379而不是 Redis 数据节点的端口默认 6379。2. 实现读写分离Java 配置仅配置 yml 文件Spring Boot 默认会连接 Master 进行读写。如果你希望利用从节点Slave分担读流量需要添加一个简单的 Java 配置类来指定读取策略。importio.lettuce.core.ReadFrom;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;importorg.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;importorg.springframework.data.redis.connection.RedisSentinelConfiguration;ConfigurationpublicclassRedisSentinelConfig{BeanpublicLettuceConnectionFactoryredisConnectionFactory(RedisSentinelConfigurationsentinelConfig){// 配置 Lettuce 客户端优先从从节点读取数据// 如果从节点不可用会自动降级回主节点LettuceClientConfigurationclientConfigLettuceClientConfiguration.builder().readFrom(ReadFrom.REPLICA_PREFERRED).build();returnnewLettuceConnectionFactory(sentinelConfig,clientConfig);}}3. 配置参数详解配置项说明spring.redis.sentinel.master逻辑名称。Spring 会问哨兵“谁是mymaster的老大”哨兵会返回当前的 Master IP。spring.redis.sentinel.nodes哨兵列表。Spring 会随机连接其中一个哨兵来获取 Master 地址。如果连接失败会自动尝试列表中的下一个。spring.redis.password数据节点密码。用于连接 Redis Master/Slave 的密码。spring.redis.sentinel.password哨兵节点密码。如果你的哨兵进程单独设置了requirepass需要配置此项。4. 常见问题排查启动报错Cannot get master address from sentinel检查master名称是否拼写正确通常默认是mymaster但也可能是master1等。检查防火墙是否开放了哨兵端口26379。确保 Spring Boot 服务器能ping通哨兵服务器。连接到了错误的 IPRedis 哨兵返回的是 Redis 实例配置的 IP。如果 Redis 部署在 Docker 或 NAT 网络后确保 Redis 实例配置的bind-ip和哨兵能识别的 IP 是 Spring Boot 服务器能访问的。Spring Boot 3.x 差异Spring Boot 3.x 的配置前缀依然是spring.data.redis在 yml 中通常简写为spring.redis配置结构基本保持不变。Spring Data Redisyml 配置中添加 Redis 分片集群配置在 Spring Data Redis 中配置Redis 分片集群Redis Cluster核心在于告诉客户端集群的“种子节点”。客户端默认是 Lettuce连接后会自动发现整个集群拓扑结构。以下是基于Spring Boot和Lettuce客户端的完整配置方案。1.application.yml配置这是最基础也是最重要的部分。你需要列出部分节点通常建议列出所有主节点或者至少 3 个节点Spring Boot 会自动识别这是一个集群环境。spring:redis:# 1. 集群配置核心cluster:# 节点列表逗号分隔或数组格式# 注意这里填写的是 Redis 数据节点的 IP:Port不是哨兵端口nodes:-192.168.1.100:7001-192.168.1.100:7002-192.168.1.100:7003-192.168.1.100:7004-192.168.1.100:7005-192.168.1.100:7006# 2. 认证与基础配置password:your_redis_password# 集群统一密码timeout:3000ms# 命令超时时间# 3. Lettuce 客户端配置推荐lettuce:pool:max-active:20max-idle:10min-idle:5max-wait:2000ms# 集群拓扑刷新配置应对主从切换cluster:refresh:adaptive:true# 自适应刷新遇到 MOVED/ASK 重定向时自动更新拓扑period:60s# 定期刷新每 60 秒强制刷新一次拓扑作为兜底 关键点说明spring.redis.cluster.nodes只要配置了此项Spring Boot 就会自动启用RedisClusterConfiguration无需手动指定host和port。节点数量不需要配置所有 6 个节点配置 3 个主节点通常就足够 Lettuce 发现全貌但为了高可用建议配置所有节点。adaptive: true非常重要。当集群发生主从切换Failover时客户端缓存的槽位Slot映射会失效。开启此配置后Lettuce 收到MOVED异常时会自动更新路由表无需重启服务。2. 实现读写分离Java 配置与哨兵模式类似默认情况下 Spring Data Redis 会优先读写主节点。如果你希望利用从节点分担读流量需要添加配置类。importio.lettuce.core.ReadFrom;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;importorg.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;importorg.springframework.data.redis.connection.RedisClusterConfiguration;ConfigurationpublicclassRedisClusterConfig{BeanpublicLettuceConnectionFactoryredisConnectionFactory(RedisClusterConfigurationclusterConfig){// 配置 Lettuce 客户端优先从从节点读取数据// 如果从节点不可用会自动降级回主节点LettuceClientConfigurationclientConfigLettuceClientConfiguration.builder().readFrom(ReadFrom.REPLICA_PREFERRED).build();returnnewLettuceConnectionFactory(clusterConfig,clientConfig);}}3. 代码使用注意事项跨 Slot 问题在分片集群中使用RedisTemplate时有一个巨大的“坑”需要注意多 Key 操作。单 Key 操作推荐set(key, value),get(key),hget(key, field)等完全没问题客户端会自动计算 Hash Slot 并路由到正确节点。多 Key 操作限制mget(key1, key2),mset(key1, val1, key2, val2)等操作要求所有 Key 必须落在同一个 Slot 上。如果key1在节点 Akey2在节点 B直接调用会报错CROSSSLOT Keys in request dont hash to the same slot。解决方案使用 Hash Tag{}如果你必须对多个 Key 进行批量操作可以使用{}包裹 Key 的公共部分强制它们落入同一个 Slot。// 错误示范可能跨 SlotredisTemplate.opsForValue().multiGet(Arrays.asList(user:1001,user:1002));// 正确示范强制使用相同的 Slot取 {} 内的内容计算 hash// 这两个 Key 都会根据 common_group 计算槽位从而落在同一个节点redisTemplate.opsForValue().multiGet(Arrays.asList({common_group}:user:1001,{common_group}:user:1002));4. 配置参数详解配置项说明spring.redis.cluster.nodes种子节点列表。客户端连接任意一个节点后会执行CLUSTER NODES命令获取完整拓扑。spring.redis.lettuce.cluster.refresh.adaptive自适应刷新。开启后当遇到重定向异常时自动触发拓扑更新是生产环境必备配置。spring.redis.lettuce.cluster.refresh.period定期刷新。作为双重保险定期后台刷新拓扑结构。spring.redis.password集群密码。Redis Cluster 通常所有节点配置相同的密码。5. 常见报错排查MOVED xxx 192.168.x.x:700x这是正常现象表示客户端请求的节点不是该 Key 的负责节点节点告诉客户端“去那边找”。解决确保开启了adaptive: trueLettuce 会自动处理。如果一直报错检查网络是否通畅或者客户端是否无法连接新的 IP如内网 IP 映射问题。CROSSSLOT Keys in request dont hash to the same slot原因执行了mget、mset或事务操作但涉及的 Key 分布在不同的槽位。解决使用{tag}语法强制 Key 落在同一槽位或者在代码中循环单 Key 操作性能稍低。连接超时检查 Redis 节点的cluster-announce-ip配置。如果 Redis 在 Docker 中必须配置该参数为宿主 IP否则客户端拿到的拓扑信息是容器内网 IP导致无法连接。