package controller import ( "context" "fmt" "github.com/redis/go-redis/v9" ) // collectRedis 采集 Redis 指标,支持单机与集群模式 // Logan.Li func (h *MiddlewareMonitorHandler) collectRedis(ctx context.Context, addr, password, mode string) (map[string]float64, error) { if mode == "" { mode = "standalone" } var ( info string dbSize int64 clusterInfo string pingErr error ) switch mode { case "cluster": rdb := redis.NewClusterClient(&redis.ClusterOptions{ Addrs: []string{addr}, Password: password, }) defer rdb.Close() pingErr = rdb.Ping(ctx).Err() if pingErr == nil { info, _ = rdb.Info(ctx).Result() dbSize, _ = rdb.DBSize(ctx).Result() clusterInfo, _ = rdb.ClusterInfo(ctx).Result() } default: rdb := redis.NewClient(&redis.Options{ Addr: addr, Password: password, DB: 0, }) defer rdb.Close() pingErr = rdb.Ping(ctx).Err() if pingErr == nil { info, _ = rdb.Info(ctx).Result() dbSize, _ = rdb.DBSize(ctx).Result() } } if pingErr != nil { return nil, fmt.Errorf("Redis 连接失败: %v", pingErr) } return buildRedisMetrics(info, dbSize, clusterInfo, mode), nil } // buildRedisMetrics 从 INFO 与 DBSIZE 构建指标 map // Logan.Li func buildRedisMetrics(info string, dbSize int64, clusterInfo, mode string) map[string]float64 { result := make(map[string]float64) if info != "" { infoMap := parseRedisInfo(info) result["redis_connected_clients"] = parseFloat(infoMap["connected_clients"]) result["redis_used_memory"] = parseFloat(infoMap["used_memory"]) result["redis_used_memory_peak"] = parseFloat(infoMap["used_memory_peak"]) result["redis_total_commands_processed"] = parseFloat(infoMap["total_commands_processed"]) result["redis_uptime_in_seconds"] = parseFloat(infoMap["uptime_in_seconds"]) result["redis_keyspace_hits"] = parseFloat(infoMap["keyspace_hits"]) result["redis_keyspace_misses"] = parseFloat(infoMap["keyspace_misses"]) result["redis_evicted_keys"] = parseFloat(infoMap["evicted_keys"]) result["redis_blocked_clients"] = parseFloat(infoMap["blocked_clients"]) result["redis_maxmemory"] = parseFloat(infoMap["maxmemory"]) result["redis_mem_fragmentation_ratio"] = parseFloat(infoMap["mem_fragmentation_ratio"]) hits := result["redis_keyspace_hits"] misses := result["redis_keyspace_misses"] if hits+misses > 0 { result["redis_hit_rate"] = hits / (hits + misses) } uptime := result["redis_uptime_in_seconds"] cmds := result["redis_total_commands_processed"] if uptime > 0 { result["redis_qps"] = cmds / uptime } } if dbSize >= 0 { result["redis_db_size"] = float64(dbSize) } if mode == "cluster" && clusterInfo != "" { ci := parseRedisInfo(clusterInfo) result["redis_cluster_known_nodes"] = parseFloat(ci["cluster_known_nodes"]) result["redis_cluster_size"] = parseFloat(ci["cluster_size"]) } return result }