Redis怎样对接Spring Boot与哨兵_通过配置spring.redis.sentinel自动感知集群拓扑变化

2次阅读

spring boot中redis哨兵配置不生效的根本原因是保留了spring.redis.host和spring.redis.port,导致自动配置优先启用单机模式;需删除这两项,并确保哨兵配置项(如master name、节点地址、密码等)准确无误且网络可达。

Redis怎样对接Spring Boot与哨兵_通过配置spring.redis.sentinel自动感知集群拓扑变化

spring.redis.sentinel 配置后不生效,连接还是打到单节点?

根本原因通常是 spring.redis.hostspring.redis.port 仍被保留。spring boot 的 Redis 自动配置会优先走单机模式——只要这两个属性存在,哨兵配置就直接被忽略。

  • 删掉 spring.redis.hostspring.redis.port,一个都不能留
  • 确保 spring.redis.sentinel.master 值和哨兵中监控的 master name 完全一致(大小写敏感,常被写成 myMaster 但实际是 mymaster
  • 检查哨兵节点地址格式:必须是 host:port,多个用逗号分隔,不能带空格或协议前缀,例如 192.168.1.10:26379,192.168.1.11:26379

哨兵切换后应用报 Cannot get Jedis connectionConnection refused

这不是配置问题,而是 Jedis 客户端缓存了旧 master 地址。哨兵完成故障转移后,新 master 的 IP:port 变了,但 Jedis 默认不会主动轮询哨兵更新,得靠重试机制触发刷新。

  • 加配置 spring.redis.jedis.pool.max-wait=2000ms,避免连接卡死
  • 必须启用哨兵的自动发现能力:Jedis 底层依赖 JedisSentinelPool,它会在每次 getConnection() 失败后主动向哨兵查一次当前 master,所以「第一次失败」是正常现象,关键看是否能恢复
  • 别在代码里手动 new Jedis() —— 必须通过 RedisTemplateJedisConnectionFactory 获取连接,否则绕过哨兵逻辑

为什么加了哨兵配置,却连不上任意一个哨兵节点?

常见于网络或权限层面,和 Spring Boot 配置本身无关。哨兵通信走的是 Redis 协议(非 http),但默认只监听本地回环,且不校验密码(除非显式配置 requirepasssentinel auth-pass)。

  • 检查哨兵配置文件中的 bind 行:若写成 bind 127.0.0.1,则外部应用无法访问,应改为 bind 0.0.0.0 或具体内网 IP
  • 确认防火墙放行哨兵端口(默认 26379),不是 Redis 的 6379
  • 如果哨兵启用了认证,必须配 spring.redis.sentinel.password;注意:这个密码是哨兵自身的密码,和 Redis master 密码(spring.redis.password)是两回事

集群拓扑变化时,应用日志刷屏 Sentinel changed to xxx 是否正常?

正常,但高频刷屏说明哨兵之间状态同步不稳定,或者客户端频繁重连。Spring Boot 2.3+ 的 Lettuce 默认开启哨兵事件监听,每次 master 切换都会触发回调并打印 INFO 日志。

  • 不想看这些日志,可加 Logging.level.redis.clients.jedis=warn
  • 更关键的是检查哨兵集群健康度:执行 redis-cli -p 26379 sentinel masters,看 num-slavesnum-other-sentinels 是否稳定,flags 是否含 odowns_down
  • Lettuce 比 Jedis 更擅长处理拓扑变更,若用 Jedis,建议升级到 3.9+ 并确认使用的是 JedisSentinelPool 而非旧版 JedisPool

哨兵模式下最易被忽略的一点:所有 Redis 客户端实例(包括后台定时任务、异步线程里的 RedisTemplate)都必须共享同一个 JedisSentinelPool 实例,否则每个线程池各自维护一套哨兵连接,会放大故障窗口。

text=ZqhQzanResources