package database import ( "context" "gofaster/internal/shared/config" "time" "github.com/go-redis/redis/v8" "go.uber.org/zap" ) type RedisClient struct { client *redis.Client logger *zap.Logger } func NewRedisClient(cfg *config.RedisConfig, logger *zap.Logger) *RedisClient { if logger == nil { logger = zap.L() } // 记录连接参数(隐藏密码) logger.Info("Initializing Redis client", zap.String("host", cfg.Host), zap.String("port", cfg.Port), zap.Int("db", cfg.DB), zap.Bool("has_password", cfg.Password != ""), ) client := redis.NewClient(&redis.Options{ Addr: cfg.Host + ":" + cfg.Port, Password: cfg.Password, DB: cfg.DB, }) // 测试连接(带超时和重试) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() retries := 3 var lastErr error for i := 0; i < retries; i++ { if _, err := client.Ping(ctx).Result(); err != nil { lastErr = err logger.Warn("Redis connection attempt failed", zap.Int("attempt", i+1), zap.Error(err), ) time.Sleep(1 * time.Second) // 延迟重试 continue } break } if lastErr != nil { logger.Warn("Failed to connect to Redis after retries, continuing without Redis", zap.Int("retries", retries), zap.Error(lastErr), ) // 返回一个空的 Redis 客户端,程序可以继续运行 return &RedisClient{ client: nil, logger: logger, } } // 监控连接状态 go monitorConnection(client, logger) logger.Info("Redis client initialized successfully") return &RedisClient{ client: client, logger: logger, } } // 监控 Redis 连接状态 func monitorConnection(client *redis.Client, logger *zap.Logger) { if client == nil { return // 如果没有 Redis 客户端,不进行监控 } ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for range ticker.C { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) _, err := client.Ping(ctx).Result() cancel() if err != nil { logger.Error("Redis connection health check failed", zap.Error(err), ) } } } func (r *RedisClient) GetClient() *redis.Client { return r.client } func (r *RedisClient) Close() error { if r.client == nil { r.logger.Info("No Redis connection to close") return nil } r.logger.Info("Closing Redis connection") return r.client.Close() }