客户端不会连接所有节点,只连目标槽位所在节点;Lettuce按需建连并回收空闲连接,JedisCluster则默认连接全部节点,真实连接数=单节点池大小×实际连接数。

Redis集群模式下,每个客户端连接真的会连到所有节点吗?
不会。客户端只连接它需要访问的节点,但“需要访问”这件事常被误判——比如用 redis-cli 直连某个节点后执行 KEYS *,看起来像在查全量数据,其实请求会被重定向或拒绝;而真正发请求前没做 ASK/MOVED 重试逻辑的客户端(如某些老版本 Jedis),可能反复连错节点,造成连接堆积。
- 标准 Redis 集群客户端(如 Lettuce、redis-py 4.0+)默认启用
cluster-support,自动维护节点拓扑,只向目标槽位所在节点发起命令 - 手动分片或使用非集群模式客户端(如直连
redis://node1:7001)时,应用会把所有请求发给单点,其他节点连接数为 0,但该节点连接池会满载甚至超限 - 连接数膨胀主因不是“连所有节点”,而是应用未复用连接、连接泄漏、或配置了过大的连接池却没限流
怎么算清一个应用实例的真实连接总数?
不能只看 maxTotal 配置值。真实连接数 =(单节点连接池大小)×(实际连接的节点数)。而后者取决于客户端是否开启集群自动发现。
- 用 Lettuce:若配置
RedisURI指向任意一个节点 +ClusterClientOptions.builder().autoReconnect(true),它启动时会通过CLUSTER NODES获取全部节点,但**只对当前请求涉及的槽位建立连接**,空闲连接会按poolConfig.setMaxIdle()回收 - 用 JedisCluster:构造时传入的
Set<hostandport></hostandport>是初始种子节点,它会主动连接全部节点并维持心跳,所以连接数 ≈maxTotal × 节点总数(除非你手动调closeConnection()) - 验证方法:在任一 Redis 节点执行
CLIENT LIST,过滤addr=字段,统计不同 IP:port 出现次数;再对比应用侧连接池监控(如 Micrometer 的connection.pool.active)
连接池参数设多少才不拖垮 Redis 节点?
没有通用数字,得按节点内存和网络句柄上限倒推。一个 Redis 实例默认最大连接数是 maxclients 10000,但实际能稳住的活跃连接远小于此——因为每个连接占内存(约 10KB)、消耗 epoll 句柄、增加命令排队延迟。
- 保守建议:单节点连接池上限 ≤ 200(Lettuce)或 ≤ 50(JedisCluster),前提是应用 QPS
- 必须关掉
testOnBorrow(Jedis)或禁用validateAfterInactivity(Lettuce),否则每次取连接都发PING,集群里变成广播风暴 - 关键配置漏项:没设
minEvictableIdleTimeMillis或timeBetweenEvictionRunsMillis,导致空闲连接长期不释放,重启节点后旧连接仍堆积在 TIME_WAIT 状态
为什么压测时连接数突增却查不到业务代码问题?
常见于日志埋点、监控 SDK 或中间件自动采集行为——比如 Spring Boot Actuator 的 redis-health-indicator 默认每 10 秒连一次所有节点做健康检查;又或者 APM 工具(如 SkyWalking)插件在集群模式下未适配,对每个节点都建独立连接池。
- 排查路径:抓包看源端口分布(
ss -tnp | grep :6379),比对进程 PID 和应用名;或用lsof -i :6379 -p $PID精确到线程级 - Spring Data Redis 2.6+ 开始支持
ClusterTopologyRefreshOptions,可关掉自动刷新或拉长间隔(dynamicRefreshSources(false)) - 最容易被忽略的一点:测试环境用了
application-dev.yml,里面spring.redis.cluster.max-redirects=5,但没配spring.redis.lettuce.pool,结果走默认无池化连接,每次 new LettuceClient → 新建 socket → 不 close
refreshPeriod,就可能让连接在后台静默增长三天才爆出来。










