You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

110 lines
2.3 KiB

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()
}