// Package redis 工具包 package redis import ( "context" "errors" "sync" "time" "github.com/redis/go-redis/v9" "github.com/runningwater/gohub/pkg/logger" ) // Client Redis 服务 type Client struct { Client *redis.Client Context context.Context } // Ping 测试 Redis 连接 // 通过 Ping 方法测试 Redis 连接是否正常 func (rds *Client) Ping() error { _, err := rds.Client.Ping(rds.Context).Result() return err } // Set 设置 Redis 键值对, 并设置过期时间 func (rds *Client) Set(key string, value any, expiration time.Duration) bool { if err := rds.Client.Set(rds.Context, key, value, expiration).Err(); err != nil { logger.ErrorString("Redis", "Set", err.Error()) return false } return true } // Get 获取 Redis 键值对 func (rds *Client) Get(key string) string { val, err := rds.Client.Get(rds.Context, key).Result() if err != nil { logger.ErrorString("Redis", "Get", err.Error()) return "" } return val } // Has 检查 Redis 中是否存在某个键 func (rds *Client) Has(key string) bool { _, err := rds.Client.Get(rds.Context, key).Result() if err != nil { if errors.Is(err, redis.Nil) { logger.ErrorString("Redis", "Has", err.Error()) } return false } return true } // Del 删除 Redis 中的键, 支持多个 key 传参 func (rds *Client) Del(keys ...string) bool { if err := rds.Client.Del(rds.Context, keys...).Err(); err != nil { logger.ErrorString("Redis", "Del", err.Error()) return false } return true } // FlushDb 清空 Redis 数据库 func (rds *Client) FlushDb() bool { if err := rds.Client.FlushDB(rds.Context).Err(); err != nil { logger.ErrorString("Redis", "FlushDb", err.Error()) return false } return true } // Increment 当参数只有 1 个时,增加 Redis 中的键值对增加 1 // 当参数有 2 个时,第一个参数为 Key,第二个参数为增加的值 int64 类型 func (rds *Client) Increment(args ...any) bool { switch len(args) { case 1: key := args[0].(string) if err := rds.Client.Incr(rds.Context, key).Err(); err != nil { logger.ErrorString("Redis", "Increment", err.Error()) return false } case 2: key := args[0].(string) value := args[1].(int64) if err := rds.Client.IncrBy(rds.Context, key, value).Err(); err != nil { logger.ErrorString("Redis", "Increment", err.Error()) return false } default: logger.ErrorString("Redis", "Increment", "参数错误, 只能传入 1 或 2 个参数") return false } return true } // Decrement 当参数只有 1 个时,减少 Redis 中的键值对减少 1 // 当参数有 2 个时,第一个参数为 Key,第二个参数为减少的值 int64 类型 func (rds *Client) Decrement(args ...any) bool { switch len(args) { case 1: key := args[0].(string) if err := rds.Client.Decr(rds.Context, key).Err(); err != nil { logger.ErrorString("Redis", "Decrement", err.Error()) return false } case 2: key := args[0].(string) value := args[1].(int64) if err := rds.Client.DecrBy(rds.Context, key, value).Err(); err != nil { logger.ErrorString("Redis", "Decrement", err.Error()) return false } default: logger.ErrorString("Redis", "Decrement", "参数错误, 只能传入 1 或 2 个参数") return false } return true } // func (rds *RedisClient) Reconnect(ctx context.Context) { // for { // err := rds.Ping() // if err == nil { // logger.InfoString("Redis", "Ping", "Redis 连接正常") // return // } // logger.ErrorString("Redis", "Ping", "Redis 连接异常,正在重连...") // // 重新连接 Redis // rds.Client = redis.NewClient(&redis.Options{ // Addr: rds.Client.Options().Addr, // Password: rds.Client.Options().Password, // DB: rds.Client.Options().DB, // }) // select { // case <-ctx.Done(): // logger.InfoString("Redis", "Reconnect", "Redis 重连已取消") // return // case <-time.After(5 * time.Second): // } // } // } // once 确保全局的 Redis 对象只实例一次 var once sync.Once // Redis 全局 Redis, 使用 db 1 var Redis *Client // ConnectRedis 连接 redis 数据库,设置全局 Redis 对象 func ConnectRedis(address, username, password string, db int) { once.Do(func() { Redis = NewClient(address, username, password, db) }) } func NewClient(address, username, password string, db int) *Client { rds := &Client{} rds.Context = context.Background() // 使用 redis 库里的 NewClient 初始化连接 rds.Client = redis.NewClient(&redis.Options{ Addr: address, Password: password, DB: db, }) err := rds.Ping() logger.LogIf(err) // ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) // defer cancel() // rds.Reconnect(ctx) return rds }