package main import ( "context" "encoding/json" "fmt" "log" "time" "github.com/redis/go-redis/v9" ) // RedisClient Redis客户端结构体 type RedisClient struct { Client *redis.Client Ctx context.Context } // RedisConfig Redis配置结构体 type RedisConfig struct { Addr string // 服务器地址:端口 Password string // 密码 DB int // 数据库编号 PoolSize int // 连接池大小 MinIdleConns int // 最小空闲连接数 DialTimeout time.Duration // 连接超时 ReadTimeout time.Duration // 读取超时 WriteTimeout time.Duration // 写入超时 PoolTimeout time.Duration // 获取连接超时 } // NewRedisClient 创建新的Redis客户端 func NewRedisClient(config *RedisConfig) *RedisClient { if config == nil { // 默认配置 - 根据您的需求设置 config = &RedisConfig{ Addr: "36.212.20.113:7963", Password: "", DB: 2, PoolSize: 10, MinIdleConns: 5, DialTimeout: 5 * time.Second, ReadTimeout: 3 * time.Second, WriteTimeout: 3 * time.Second, PoolTimeout: 4 * time.Second, } } rdb := redis.NewClient(&redis.Options{ Addr: config.Addr, Password: config.Password, DB: config.DB, PoolSize: config.PoolSize, MinIdleConns: config.MinIdleConns, DialTimeout: config.DialTimeout, ReadTimeout: config.ReadTimeout, WriteTimeout: config.WriteTimeout, PoolTimeout: config.PoolTimeout, }) return &RedisClient{ Client: rdb, Ctx: context.Background(), } } // Close 关闭Redis连接 func (r *RedisClient) Close() error { return r.Client.Close() } // Ping 测试连接 func (r *RedisClient) Ping() error { pong, err := r.Client.Ping(r.Ctx).Result() if err != nil { return fmt.Errorf("Redis连接失败: %v", err) } log.Printf("Redis连接成功: %s", pong) return nil } // ==================== 字符串操作 ==================== // Set 设置键值对 func (r *RedisClient) Set(key string, value interface{}, expiration time.Duration) error { err := r.Client.Set(r.Ctx, key, value, expiration).Err() if err != nil { return fmt.Errorf("设置键 %s 失败: %v", key, err) } return nil } // Get 获取字符串值 func (r *RedisClient) Get(key string) (string, error) { val, err := r.Client.Get(r.Ctx, key).Result() if err == redis.Nil { return "", fmt.Errorf("键 %s 不存在", key) } else if err != nil { return "", fmt.Errorf("获取键 %s 失败: %v", key, err) } return val, nil } // GetInt 获取整数值 func (r *RedisClient) GetInt(key string) (int, error) { val, err := r.Client.Get(r.Ctx, key).Int() if err == redis.Nil { return 0, fmt.Errorf("键 %s 不存在", key) } else if err != nil { return 0, fmt.Errorf("获取键 %s 失败: %v", key, err) } return val, nil } // GetInt64 获取64位整数值 func (r *RedisClient) GetInt64(key string) (int64, error) { val, err := r.Client.Get(r.Ctx, key).Int64() if err == redis.Nil { return 0, fmt.Errorf("键 %s 不存在", key) } else if err != nil { return 0, fmt.Errorf("获取键 %s 失败: %v", key, err) } return val, nil } // GetFloat64 获取浮点数值 func (r *RedisClient) GetFloat64(key string) (float64, error) { val, err := r.Client.Get(r.Ctx, key).Float64() if err == redis.Nil { return 0, fmt.Errorf("键 %s 不存在", key) } else if err != nil { return 0, fmt.Errorf("获取键 %s 失败: %v", key, err) } return val, nil } // GetBool 获取布尔值 func (r *RedisClient) GetBool(key string) (bool, error) { val, err := r.Client.Get(r.Ctx, key).Bool() if err == redis.Nil { return false, fmt.Errorf("键 %s 不存在", key) } else if err != nil { return false, fmt.Errorf("获取键 %s 失败: %v", key, err) } return val, nil } // SetNX 只有当键不存在时设置值 func (r *RedisClient) SetNX(key string, value interface{}, expiration time.Duration) (bool, error) { success, err := r.Client.SetNX(r.Ctx, key, value, expiration).Result() if err != nil { return false, fmt.Errorf("SetNX操作失败: %v", err) } return success, nil } // SetXX 只有当键存在时设置值 func (r *RedisClient) SetXX(key string, value interface{}, expiration time.Duration) (bool, error) { success, err := r.Client.SetXX(r.Ctx, key, value, expiration).Result() if err != nil { return false, fmt.Errorf("SetXX操作失败: %v", err) } return success, nil } // MSet 批量设置键值对 func (r *RedisClient) MSet(values map[string]interface{}) error { pairs := make([]interface{}, 0, len(values)*2) for k, v := range values { pairs = append(pairs, k, v) } err := r.Client.MSet(r.Ctx, pairs...).Err() if err != nil { return fmt.Errorf("批量设置失败: %v", err) } return nil } // MGet 批量获取值 func (r *RedisClient) MGet(keys ...string) ([]interface{}, error) { vals, err := r.Client.MGet(r.Ctx, keys...).Result() if err != nil { return nil, fmt.Errorf("批量获取失败: %v", err) } return vals, nil } // Incr 自增1 func (r *RedisClient) Incr(key string) (int64, error) { val, err := r.Client.Incr(r.Ctx, key).Result() if err != nil { return 0, fmt.Errorf("自增失败: %v", err) } return val, nil } // IncrBy 自增指定值 func (r *RedisClient) IncrBy(key string, value int64) (int64, error) { val, err := r.Client.IncrBy(r.Ctx, key, value).Result() if err != nil { return 0, fmt.Errorf("自增 %d 失败: %v", value, err) } return val, nil } // Decr 自减1 func (r *RedisClient) Decr(key string) (int64, error) { val, err := r.Client.Decr(r.Ctx, key).Result() if err != nil { return 0, fmt.Errorf("自减失败: %v", err) } return val, nil } // DecrBy 自减指定值 func (r *RedisClient) DecrBy(key string, value int64) (int64, error) { val, err := r.Client.DecrBy(r.Ctx, key, value).Result() if err != nil { return 0, fmt.Errorf("自减 %d 失败: %v", value, err) } return val, nil } // Append 追加字符串 func (r *RedisClient) Append(key, value string) (int64, error) { length, err := r.Client.Append(r.Ctx, key, value).Result() if err != nil { return 0, fmt.Errorf("追加字符串失败: %v", err) } return length, nil } // StrLen 获取字符串长度 func (r *RedisClient) StrLen(key string) (int64, error) { length, err := r.Client.StrLen(r.Ctx, key).Result() if err != nil { return 0, fmt.Errorf("获取字符串长度失败: %v", err) } return length, nil } // ==================== 键操作 ==================== // Exists 检查键是否存在 func (r *RedisClient) Exists(keys ...string) (int64, error) { count, err := r.Client.Exists(r.Ctx, keys...).Result() if err != nil { return 0, fmt.Errorf("检查键是否存在失败: %v", err) } return count, nil } // Del 删除键 func (r *RedisClient) Del(keys ...string) (int64, error) { count, err := r.Client.Del(r.Ctx, keys...).Result() if err != nil { return 0, fmt.Errorf("删除键失败: %v", err) } return count, nil } // Expire 设置过期时间 func (r *RedisClient) Expire(key string, expiration time.Duration) (bool, error) { success, err := r.Client.Expire(r.Ctx, key, expiration).Result() if err != nil { return false, fmt.Errorf("设置过期时间失败: %v", err) } return success, nil } // TTL 获取剩余过期时间 func (r *RedisClient) TTL(key string) (time.Duration, error) { ttl, err := r.Client.TTL(r.Ctx, key).Result() if err != nil { return 0, fmt.Errorf("获取过期时间失败: %v", err) } return ttl, nil } // Persist 移除过期时间 func (r *RedisClient) Persist(key string) (bool, error) { success, err := r.Client.Persist(r.Ctx, key).Result() if err != nil { return false, fmt.Errorf("移除过期时间失败: %v", err) } return success, nil } // Type 获取键类型 func (r *RedisClient) Type(key string) (string, error) { typeStr, err := r.Client.Type(r.Ctx, key).Result() if err != nil { return "", fmt.Errorf("获取键类型失败: %v", err) } return typeStr, nil } // Keys 查找所有匹配的键 func (r *RedisClient) Keys(pattern string) ([]string, error) { keys, err := r.Client.Keys(r.Ctx, pattern).Result() if err != nil { return nil, fmt.Errorf("查找键失败: %v", err) } return keys, nil } // RandomKey 随机获取一个键 func (r *RedisClient) RandomKey() (string, error) { key, err := r.Client.RandomKey(r.Ctx).Result() if err != nil { return "", fmt.Errorf("随机获取键失败: %v", err) } return key, nil } // Rename 重命名键 func (r *RedisClient) Rename(key, newKey string) error { err := r.Client.Rename(r.Ctx, key, newKey).Err() if err != nil { return fmt.Errorf("重命名键失败: %v", err) } return nil } // RenameNX 只有当新键不存在时重命名 func (r *RedisClient) RenameNX(key, newKey string) (bool, error) { success, err := r.Client.RenameNX(r.Ctx, key, newKey).Result() if err != nil { return false, fmt.Errorf("重命名键失败: %v", err) } return success, nil } // ==================== Hash操作 ==================== // HSet 设置Hash字段 func (r *RedisClient) HSet(key string, values ...interface{}) error { err := r.Client.HSet(r.Ctx, key, values...).Err() if err != nil { return fmt.Errorf("设置Hash失败: %v", err) } return nil } // HGet 获取Hash字段 func (r *RedisClient) HGet(key, field string) (string, error) { val, err := r.Client.HGet(r.Ctx, key, field).Result() if err == redis.Nil { return "", fmt.Errorf("字段 %s 不存在", field) } else if err != nil { return "", fmt.Errorf("获取Hash字段失败: %v", err) } return val, nil } // HGetAll 获取所有Hash字段 func (r *RedisClient) HGetAll(key string) (map[string]string, error) { vals, err := r.Client.HGetAll(r.Ctx, key).Result() if err != nil { return nil, fmt.Errorf("获取所有Hash字段失败: %v", err) } return vals, nil } // HDel 删除Hash字段 func (r *RedisClient) HDel(key string, fields ...string) (int64, error) { count, err := r.Client.HDel(r.Ctx, key, fields...).Result() if err != nil { return 0, fmt.Errorf("删除Hash字段失败: %v", err) } return count, nil } // HExists 检查Hash字段是否存在 func (r *RedisClient) HExists(key, field string) (bool, error) { exists, err := r.Client.HExists(r.Ctx, key, field).Result() if err != nil { return false, fmt.Errorf("检查Hash字段失败: %v", err) } return exists, nil } // HKeys 获取所有Hash字段名 func (r *RedisClient) HKeys(key string) ([]string, error) { keys, err := r.Client.HKeys(r.Ctx, key).Result() if err != nil { return nil, fmt.Errorf("获取Hash字段名失败: %v", err) } return keys, nil } // HVals 获取所有Hash字段值 func (r *RedisClient) HVals(key string) ([]string, error) { vals, err := r.Client.HVals(r.Ctx, key).Result() if err != nil { return nil, fmt.Errorf("获取Hash字段值失败: %v", err) } return vals, nil } // HLen 获取Hash字段数量 func (r *RedisClient) HLen(key string) (int64, error) { count, err := r.Client.HLen(r.Ctx, key).Result() if err != nil { return 0, fmt.Errorf("获取Hash字段数量失败: %v", err) } return count, nil } // HIncrBy Hash字段自增 func (r *RedisClient) HIncrBy(key, field string, incr int64) (int64, error) { val, err := r.Client.HIncrBy(r.Ctx, key, field, incr).Result() if err != nil { return 0, fmt.Errorf("Hash字段自增失败: %v", err) } return val, nil } // ==================== List操作 ==================== // LPush 从左侧插入列表 func (r *RedisClient) LPush(key string, values ...interface{}) (int64, error) { count, err := r.Client.LPush(r.Ctx, key, values...).Result() if err != nil { return 0, fmt.Errorf("LPush失败: %v", err) } return count, nil } // RPush 从右侧插入列表 func (r *RedisClient) RPush(key string, values ...interface{}) (int64, error) { count, err := r.Client.RPush(r.Ctx, key, values...).Result() if err != nil { return 0, fmt.Errorf("RPush失败: %v", err) } return count, nil } // LPop 从左侧弹出元素 func (r *RedisClient) LPop(key string) (string, error) { val, err := r.Client.LPop(r.Ctx, key).Result() if err == redis.Nil { return "", fmt.Errorf("列表为空") } else if err != nil { return "", fmt.Errorf("LPop失败: %v", err) } return val, nil } // RPop 从右侧弹出元素 func (r *RedisClient) RPop(key string) (string, error) { val, err := r.Client.RPop(r.Ctx, key).Result() if err == redis.Nil { return "", fmt.Errorf("列表为空") } else if err != nil { return "", fmt.Errorf("RPop失败: %v", err) } return val, nil } // LLen 获取列表长度 func (r *RedisClient) LLen(key string) (int64, error) { length, err := r.Client.LLen(r.Ctx, key).Result() if err != nil { return 0, fmt.Errorf("获取列表长度失败: %v", err) } return length, nil } // LRange 获取列表范围 func (r *RedisClient) LRange(key string, start, stop int64) ([]string, error) { vals, err := r.Client.LRange(r.Ctx, key, start, stop).Result() if err != nil { return nil, fmt.Errorf("获取列表范围失败: %v", err) } return vals, nil } // ==================== Set操作 ==================== // SAdd 添加集合元素 func (r *RedisClient) SAdd(key string, members ...interface{}) (int64, error) { count, err := r.Client.SAdd(r.Ctx, key, members...).Result() if err != nil { return 0, fmt.Errorf("SAdd失败: %v", err) } return count, nil } // SMembers 获取所有集合成员 func (r *RedisClient) SMembers(key string) ([]string, error) { members, err := r.Client.SMembers(r.Ctx, key).Result() if err != nil { return nil, fmt.Errorf("获取集合成员失败: %v", err) } return members, nil } // SIsMember 检查是否是集合成员 func (r *RedisClient) SIsMember(key string, member interface{}) (bool, error) { exists, err := r.Client.SIsMember(r.Ctx, key, member).Result() if err != nil { return false, fmt.Errorf("检查集合成员失败: %v", err) } return exists, nil } // SCard 获取集合基数 func (r *RedisClient) SCard(key string) (int64, error) { count, err := r.Client.SCard(r.Ctx, key).Result() if err != nil { return 0, fmt.Errorf("获取集合基数失败: %v", err) } return count, nil } // ==================== Sorted Set操作 ==================== // ZAdd 添加有序集合元素 func (r *RedisClient) ZAdd(key string, members ...redis.Z) (int64, error) { count, err := r.Client.ZAdd(r.Ctx, key, members...).Result() if err != nil { return 0, fmt.Errorf("ZAdd失败: %v", err) } return count, nil } // ZRange 获取有序集合范围 func (r *RedisClient) ZRange(key string, start, stop int64) ([]string, error) { vals, err := r.Client.ZRange(r.Ctx, key, start, stop).Result() if err != nil { return nil, fmt.Errorf("ZRange失败: %v", err) } return vals, nil } // ZRangeWithScores 获取有序集合范围和分数 func (r *RedisClient) ZRangeWithScores(key string, start, stop int64) ([]redis.Z, error) { vals, err := r.Client.ZRangeWithScores(r.Ctx, key, start, stop).Result() if err != nil { return nil, fmt.Errorf("ZRangeWithScores失败: %v", err) } return vals, nil } // ZScore 获取元素分数 func (r *RedisClient) ZScore(key, member string) (float64, error) { score, err := r.Client.ZScore(r.Ctx, key, member).Result() if err == redis.Nil { return 0, fmt.Errorf("元素不存在") } else if err != nil { return 0, fmt.Errorf("获取分数失败: %v", err) } return score, nil } // ==================== JSON序列化操作 ==================== // SetJSON 将结构体序列化为JSON并存储 func (r *RedisClient) SetJSON(key string, data interface{}, expiration time.Duration) error { jsonData, err := json.Marshal(data) if err != nil { return fmt.Errorf("JSON序列化失败: %v", err) } return r.Set(key, jsonData, expiration) } // GetJSON 获取JSON并反序列化到结构体 func (r *RedisClient) GetJSON(key string, result interface{}) error { data, err := r.Get(key) if err != nil { return err } err = json.Unmarshal([]byte(data), result) if err != nil { return fmt.Errorf("JSON反序列化失败: %v", err) } return nil } // ==================== 分布式锁 ==================== // TryLock 尝试获取分布式锁 func (r *RedisClient) TryLock(key string, expiration time.Duration) (bool, error) { success, err := r.Client.SetNX(r.Ctx, key, "locked", expiration).Result() if err != nil { return false, fmt.Errorf("获取锁失败: %v", err) } return success, nil } // ReleaseLock 释放分布式锁 func (r *RedisClient) ReleaseLock(key string) error { // 使用Lua脚本确保原子性操作 script := ` if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end ` result, err := r.Client.Eval(r.Ctx, script, []string{key}, "locked").Result() if err != nil { return fmt.Errorf("释放锁失败: %v", err) } if result.(int64) == 0 { return fmt.Errorf("锁已释放或不属于当前客户端") } return nil } // ==================== 管道操作 ==================== // Pipeline 执行管道操作 func (r *RedisClient) Pipeline(fn func(pipe redis.Pipeliner) error) error { pipe := r.Client.Pipeline() err := fn(pipe) if err != nil { return err } _, err = pipe.Exec(r.Ctx) return err } // ==================== 事务操作 ==================== // Watch 监视键并执行事务 func (r *RedisClient) Watch(fn func(tx *redis.Tx) error, keys ...string) error { err := r.Client.Watch(r.Ctx, fn, keys...) if err != nil { return fmt.Errorf("事务执行失败: %v", err) } return nil } // ==================== 发布订阅 ==================== // Publish 发布消息 func (r *RedisClient) Publish(channel string, message interface{}) error { err := r.Client.Publish(r.Ctx, channel, message).Err() if err != nil { return fmt.Errorf("发布消息失败: %v", err) } return nil } // Subscribe 订阅频道 func (r *RedisClient) Subscribe(channels ...string) *redis.PubSub { return r.Client.Subscribe(r.Ctx, channels...) } // ==================== 数据库操作 ==================== // SelectDB 切换数据库 // 注意:go-redis/v9的Client没有直接的Select方法,需要通过Do命令执行 func (r *RedisClient) SelectDB(db int) error { // 使用Do命令执行SELECT cmd := redis.NewCmd(r.Ctx, "SELECT", db) err := r.Client.Process(r.Ctx, cmd) if err != nil { return fmt.Errorf("切换数据库到 %d 失败: %v", db, err) } // 检查命令执行结果 _, err = cmd.Result() if err != nil { return fmt.Errorf("切换数据库到 %d 失败: %v", db, err) } return nil } //// 主函数 //func main() { //}