Spring Boot 接入 Redis Sentinel:自动主从切换与读写分离实战(修复单机多实例与 Sentinel 配置坑) - 指南

前两篇我们已经完成了:

  • 第一篇:《Redis单机多实例集群实战指南》 在一台机器上运行多个 Redis 实例(7001 主 + 7002/7003 从),构建主从环境。
  • 第二篇:《手把手搭建 Redis Sentinel 高可用集群》 在主从之上增加三哨兵(27001/27002/27003),实现自动故障转移。

但如果你直接用这两个环境去接入 Spring Boot 应用,会遇到连接报错:

Unable to connect to 127.0.0.1:7002
Unable to connect to 127.0.0.1:7003

原因就在于前两篇的配置对外广播了错误的 IP(127.0.0.1)。本文将带你修复这些坑,并完成 Spring Boot 应用接入 Redis Sentinel,实现自动主从切换与读写分离。


一、环境说明

  • Redis 主从:7001(主)、7002(从)、7003(从)
  • Sentinel 集群:27001、27002、27003
  • Redis 密码:1111(示例)
  • Spring Boot:基于 spring-data-redis(Lettuce 驱动)

二、修复前两篇遗留的坑(并且打开防火墙7001/2/3,27001/2/3)

1. Redis 实例(主从)需指定对外公告地址

redis.conf 中添加:

replicaof 192.168.1.100 7003   # 改成真实宿主机以及对应端口

主节点(7001)也建议修改:

replicaof 192.168.1.100 7003   # 改成真实宿主机以及对应端口

2. Sentinel 需指定对外公告地址

在每个 sentinel.conf 中添加:

sentinel announce-ip 192.168.1.100	# 27002 / 27003 分别改

3. 刷新 Sentinel 配置

修改配置后,在每个 Sentinel 上执行:

redis-cli -h 192.168.1.100 -p 27001 SENTINEL RESET mymaster
redis-cli -h 192.168.1.100 -p 27001 SENTINEL flushconfig

执行后,检查:

redis-cli -h 192.168.1.100 -p 27001 SENTINEL slaves mymaster

输出里的 ip= 字段应为真实 IP,而不是 127.0.0.1

这样,应用端才能获取正确的拓扑。


三、Spring Boot 应用接入配置

1. 依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. application.yml

spring:
redis:
sentinel:
master: mymaster
nodes:
- 192.168.1.100:27001
- 192.168.1.100:27002
- 192.168.1.100:27003
password: 1111
timeout: 3000

3. 开启 Lettuce 读写分离策略

/**
* @author: takumilove
* @description: Redis 配置类
* @date: 2025/9/23
**/
@Configuration
@ConditionalOnClass(ReadFrom.class)
public class RedisConfig
{
/**
* Lettuce 配置:读写分离,固定使用 REPLICA_PREFERRED
*/
@Bean
public LettuceClientConfigurationBuilderCustomizer lettuceReadFromCustomizer() {
return builder -> builder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
}

4. 示例接口

@RestController
public class HelloController
{
@Autowired
private StringRedisTemplate redisTemplate;
@GetMapping("/set/{key}/{value}")
public String set(@PathVariable String key, @PathVariable String value) {
redisTemplate.opsForValue().set(key, value);
return "OK";
}
@GetMapping("/get/{key}")
public String get(@PathVariable String key) {
return redisTemplate.opsForValue().get(key);
}
}

四、正常运行验证

curl "http://localhost:8080/set/hello/world"
curl "http://localhost:8080/get/hello"
  • 写操作走 master(7001)
    在这里插入图片描述

  • 读操作走 replica(7002/7003)
    在这里插入图片描述


五、故障切换实战(模拟主库宕机)

在高可用架构里,最重要的能力就是:主库挂了,业务还能继续跑
我们来手动测试一下。

1. 主库下线

执行命令,关闭主库(7001):

redis-cli -h 192.168.1.100 -p 7001 -a 1111 shutdown

在这里插入图片描述

此时,Sentinel 会立刻发现主库不可用,经过投票仲裁后,将某个从库(如 7003)提升为新的主库,并让其他从库自动跟随它。
在这里插入图片描述
在这里插入图片描述

2. Spring Boot 日志分析

应用端不需要重启,Lettuce 会自动刷新拓扑。日志里能看到几个关键阶段:

(1) 读写异常触发

应用在 7002 上尝试 GET 时,连接被重置:
在这里插入图片描述

(2) 客户端自动重连

Lettuce 马上对新主从发起重连:
在这里插入图片描述
同样在 7003 上:
在这里插入图片描述

(3) 写请求切换到新主库

不久后,写操作已经走向新的主库(7003):


说明客户端已经从哨兵获取到新的拓扑,写操作不再指向旧主(7001)。

3. 验证结果

  • 应用接口在主库宕机期间,短暂会报 Connection reset
  • 很快,Lettuce 自动重连并完成拓扑刷新;
  • 读写请求恢复正常,新的主库(7003)继续提供写服务。

整个过程 无需重启应用,Redis 高可用方案真正落地。


六、总结与闭环

本文修复了前两篇文章中的坑:

  • 从库和 Sentinel 默认广播是 127.0.0.1,导致应用连接失败
  • 修复方式是显式配置 replicaof 为真实IP与 sentinel announce-ip
  • 并演示了 Spring Boot 如何接入 Redis Sentinel,实现自动主从切换与读写分离

通过最后的 故障切换测试,我们可以清楚看到:即使主库宕机,应用也能在 Sentinel 的帮助下快速恢复,这才是真正的高可用。

posted @ 2025-09-24 22:12  yxysuanfa  阅读(6)  评论(0)    收藏  举报