fix(redis): 集群拓扑解析错误,跨机集群节点被强制指向种子机
【现象】Redis 集群实例查 keys 报 500:
Redis cluster connection failed: dial tcp 172.19.16.16:6005: connect: connection refused
【根因】handler/redis.go 解析 CLUSTER SLOTS:
nodeAddr := slot.Nodes[0].Addr // Redis 上报的真实地址 172.19.16.30:6005
if idx := strings.LastIndex(nodeAddr, ":"); idx >= 0 {
nodeAddr = instance.Host + nodeAddr[idx:] // 强制改写成 种子机主机 + 原端口
}
该逻辑假设「集群所有节点在同一台机器、只是端口不同」。
对跨机集群(16/30/59 三台)会把所有节点地址破坏成
172.19.16.16:6002 / :6003 / :6005 —— 这些端口在 16 上根本不存在 → refused。
【修复】
仅当 Redis 上报空 IP / 127.0.0.1 / 0.0.0.0 时才用配置 host 兜底(NAT/端口映射场景),
其余情况一律保留 Redis 上报的真实主机地址。
【附带数据修复(非代码)】
实例 5 host: pre-mysql.astx.club → 172.19.16.2
原因:pre-mysql.astx.club 公网 DNS 解析到 43.135.53.180(另一环境 MySQL),
认证失败 → 前端数据库下拉为空、无法选择数据库。
【验证】
GET /api/v1/redis/4/keys?db=0&pattern=* → 200
{"cluster":true,"keys":[{"key":"24H_rate_limit_10001_...","type":"string","ttl":42901000},
{"key":"CEX:FOLLOW:FOLLOWERS:TRADFI:97127836","type":"hash"},...]}
GET /api/v1/redis/4/dbs → 200 {"cluster":true,"dbs":[0]}
GET /api/v1/instances/5/databases → 200 返回 25 个库
["cex_activity","cex_admin","cex_agent",...,"cex_user","cex_xxl_job"]
镜像 sha256:165992ef79d5
This commit is contained in:
1 parent
6b81dbbd4a
commit
f19a84f37e
1 file changed
+10
-4
@@ -3,6 +3,7 @@ package handler
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -393,10 +394,15 @@ func getRedisClient(instance *model.Instance, db int) (*redisClientWrapper, erro
|
||||
if len(slot.Nodes) == 0 {
|
||||
continue
|
||||
}
|
||||
nodeAddr := slot.Nodes[0].Addr
|
||||
if idx := strings.LastIndex(nodeAddr, ":"); idx >= 0 {
|
||||
nodeAddr = instance.Host + nodeAddr[idx:]
|
||||
}
|
||||
nodeAddr := slot.Nodes[0].Addr
|
||||
// 只在 Redis 上报空/回环地址时才用配置 host 兜底(NAT / 端口映射场景)。
|
||||
// 多机集群必须保留 Redis 上报的真实主机,否则会把跨机节点全部指向种子机,
|
||||
// 导致 "dial tcp <种子机>:<其他机器的端口>: connection refused"。
|
||||
if h, p, err := net.SplitHostPort(nodeAddr); err == nil {
|
||||
if h == "" || h == "127.0.0.1" || h == "0.0.0.0" {
|
||||
nodeAddr = net.JoinHostPort(instance.Host, p)
|
||||
}
|
||||
}
|
||||
if !seen[nodeAddr] {
|
||||
seen[nodeAddr] = true
|
||||
addrs = append(addrs, nodeAddr)
|
||||
|
||||
Reference in new issue
Block a user