Go 中使用 Redis 做缓存入门

使用 go-redis 实现 Cache-Aside:连接与 TTL、区分缓存未命中和连接错误、取消传播、回填处理与一致性边界,并说明高可用和数据库降级保护前提。

最佳实践
应用程序模块协作插画

本文依据官方文档整理,未执行运行验证或性能基准。代码片段展示局部用法,业务函数、数据和环境需按项目补齐;版本与配置以所引文档为准。

直接回答:Go 用 go-redis 客户端操作 Redis:redis.NewClient 创建复用客户端,Set(带 TTL)写缓存、Get 读缓存、Del 失效。标准缓存模式是 Cache-Aside——先查缓存,未命中查库并回填,写库后删缓存。单机适合本地学习,生产拓扑按可用性与容量要求选择。

连接

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

rdb := redis.NewClient(&redis.Options{
    Addr: "localhost:6379",
})
if err := rdb.Ping(ctx).Err(); err != nil { log.Fatal(err) }

缓存读写删

// 写:带 10 分钟 TTL
if err := rdb.Set(ctx, "user:1", userJSON, 10*time.Minute).Err(); err != nil {
    return err
}

// 读:区分"未命中"与"出错"
val, err := rdb.Get(ctx, "user:1").Result()
if errors.Is(err, redis.Nil) { /* 未命中 */ } else if err != nil { return err }
_ = val

// 删:数据更新后主动失效
if err := rdb.Del(ctx, "user:1").Err(); err != nil { return err }

Cache-Aside 完整模式

func GetUser(ctx context.Context, id int) (*User, error) {
    key := fmt.Sprintf("user:%d", id)
    s, err := rdb.Get(ctx, key).Result()
    if err == nil {
        var u User
        if err := json.Unmarshal([]byte(s), &u); err == nil {
            return &u, nil
        }
        log.Printf("cache decode failed for user ID %d", id)
    } else if !errors.Is(err, redis.Nil) {
        if ctx.Err() != nil { return nil, ctx.Err() }
        log.Printf("cache read failed: %v", err)
    }
    u, err := queryDB(ctx, id) // 使用受限流保护且支持 context 的项目查询函数
    if err != nil { return nil, err }
    b, err := json.Marshal(u)
    if err != nil { return nil, err }
    if err := rdb.Set(ctx, key, b, 10*time.Minute).Err(); err != nil {
        log.Printf("cache refill failed: %v", err)
    }
    return u, nil
}

写路径:更新数据库后 Del 缓存(不是 Set)——删除是常见的失效策略,但无法保证强一致:并发读回填旧值、删除失败都可能留下陈旧缓存。提交数据库事务后再失效,配置 TTL、失败重试/可靠事件和数据版本检查。

生产注意

  • TTL 加抖动:10min + rand(0~2min) 防缓存雪崩(大批 key 同时过期打穿数据库)
  • 空值缓存:只有确认业务记录不存在时才缓存短 TTL 空结果,数据库超时或权限错误不能伪装成不存在
  • 序列化:JSON 够用;性能敏感看 MessagePack/Protobuf

缓存效果应同时看命中数、回源耗时和 Redis 调用失败。应用先为命中与未命中分别记录结果;使用观测云时,再按 Redis 集成接入实例指标,对照测试期间的请求变化。仅看到 Redis 响应很快,不能证明缓存命中了业务请求。

常见问题(FAQ)

Q:缓存和数据库一致性怎么保证?
A:Cache-Aside 提供的是可控的陈旧窗口而非强一致保证。严格一致的读取应回源或采用业务版本校验;CDC 失效也有延迟、重放与交付失败需要处理。

Q:Redis 挂了怎么办?
A:缓存层必须可降级:Get 出错直接查库(并限流保护数据库),同时告警。缓存是加速器不是依赖项。

Q:单机 Redis 够用吗?
A:持久化不等于高可用。单实例故障会影响缓存;Sentinel/托管故障切换及 Cluster 需按需求选择,从副本读取还可能读到旧数据。客户端由应用长期复用并在退出时 Close;生产应配置认证、TLS及网络访问控制。

官方参考

资料核对日期:2026-09-29。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台