Redis 集成:go-redis 客户端、缓存读写、连接池参数

Redis 常用来做缓存、分布式限流与登录态。go-redis 是社区最主流的客户端,v9 需要 Go 1.18+,包路径为 github.com/redis/go-redis/v9,API 以官方仓库 README 为准。

1. 安装与连接

import (
    "context"
    "time"

    "github.com/redis/go-redis/v9"
)

rdb := redis.NewClient(&redis.Options{
    Addr:         "127.0.0.1:6379",
    Password:     "", // 无密码留空
    DB:           0,
    DialTimeout:  5 * time.Second,
    ReadTimeout:  3 * time.Second,
    WriteTimeout: 3 * time.Second,
})

ctx := context.Background()
if err := rdb.Ping(ctx).Err(); err != nil {
    log.Fatalf("ping redis: %v", err)
}
defer rdb.Close()

v9 起所有命令都要显式传 context.Context,这是与旧版最大的区别。

2. 缓存读写

核心套路:先查 Redis,命中直接返回;未命中回源数据库再回填并设置过期时间:

func GetUser(ctx context.Context, id int) (*User, error) {
    val, err := rdb.Get(ctx, "user:"+strconv.Itoa(id)).Result()
    if err == nil { // 命中
        var u User
        json.Unmarshal([]byte(val), &u)
        return &u, nil
    }
    if !errors.Is(err, redis.Nil) { // 非“键不存在”的真实错误
        return nil, err
    }
    u, err := findUserByID(ctx, id) // 未命中:回源数据库
    if err != nil {
        return nil, err
    }
    data, _ := json.Marshal(u)
    rdb.Set(ctx, "user:"+strconv.Itoa(id), data, 5*time.Minute)
    return u, nil
}

键不存在的错误是哨兵值 redis.Nil,必须用 errors.Is(err, redis.Nil) 判断,不能把其他网络错误当“未命中”处理。

3. 连接池参数

redis.Options 里的池参数建议按负载调整,默认值随版本略有差异,以官方文档为准:

  • PoolSize:单实例最大连接数;
  • MinIdleConns:常驻空闲连接,压延迟建议设 8 以上;
  • ConnMaxIdleTime:空闲连接回收时间;
  • ConnMaxLifetime:连接最大存活时间,建议设置以轮换底层 TCP;
  • DialTimeout / ReadTimeout / WriteTimeout:建连与读写超时。
rdb := redis.NewClient(&redis.Options{
    Addr:            "127.0.0.1:6379",
    PoolSize:        50,
    MinIdleConns:    10,
    ConnMaxIdleTime: 30 * time.Minute,
    ConnMaxLifetime: time.Hour,
})

4. 在 Gin 里使用

*redis.Client 做成全局单例或注入到 handler,调用时复用请求上下文,请求结束连接自动归还连接池,无需手动管理:

val, err := rdb.Get(c.Request.Context(), key).Result()

注意点

  • 每次请求都 redis.NewClient 是错误用法,客户端应全局单例、程序退出时才 Close。
  • 缓存 value 建议存 JSON 字符串或二进制,别把结构体直接塞进去。
  • 更新数据后记得删/刷新相关缓存键,防止脏读。
  • 缓存穿透/雪崩的缓解(空值缓存、随机过期)属架构话题,本章不展开。

小结

go-redis v9 的统一签名是「命令(ctx, 参数...).Result()/Err()」。记住三点:redis.Nil 判空、连接池集中配置、客户端全局复用,缓存层就能平稳跑起来。命令全集与选项默认值见官方 README 与 pkg.go.dev。

笔记加载中…