连不上或超时主因是地址错误、未启连接池、DNS失败;需显式配置Options、用Context控制超时、合理设PoolSize;缓存操作要防panic、穿透、击穿;handler中须透传ctx防goroutine堆积。
redis.Client 连 Redis 时,为什么连不上或超时?常见原因是没设对地址、没开连接池、或没处理 DNS 解析失败。默认 redis.NewClient 不会主动拨号验证,直到第一次 Get 或 Set 才报错。
redis.Options{Addr: "localhost:6379", Password: "", DB: 0} 显式指定,别依赖环境变量或空字符串 fallbackContext 超时控制:比如 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second),再传给 client.Ping(ctx) 主动探测PoolSize: 10 起调,高并发 Web 服务可设到 50–100,但注意 Redis 本身 maxclients 限制(默认 10000)Set 和 Get 怎么写才安全?直接序列化结构体进 Redis 容易出问题:字段变动、类型不一致、JSON tag 错漏都会导致反序列失败,且没有类型保护。
json.Marshal + json.Unmarshal
gob(跨语言/版本不兼容)Set 必须带过期时间:client.Set(ctx, "user:123", dataBytes, 30*time.Minute),避免脏数据长期滞留Get 后先检查 val.Err() == redis.Nil,再解码;别直接 val.Val(),否则命中空值会 panicval := client.Get(ctx, "user:123")
if val.Err() == redis.Nil {
// 缓存未命中,查 DB 并写入
} else if val.Err() != nil {
// 网络或 Redis 错误
} else {
json.Unmarshal(val.Val(), &user)
}
穿透(查不存在的 ID)和击穿(热点 key 过期瞬间大量请求打到 DB)在 Go Web 中必须主动防御,Redis 客户端本身不提供自动兜底。
client.Set(ctx, "user:999999", "null", 2*time.Minute),读到 "null" 字符串就跳过 DB 查询SET key value EX 300 NX 原子操作(即 client.SetNX),只在 key 不存在时设值;配合双检锁(double-checked locking)逻辑redislock 库或基于 EVAL 的 Lua 脚本实现分布式锁,但要注意锁释放失败会导致死锁不是 Redis 本身慢,而是 Go HTTP server 默认每请求一个 goroutine,若每个 handler 都同步阻塞等 Redis 返回,goroutine 会堆积,尤其当 Redis 响应延迟升高时。
Get 直到成功),这会卡住整个 goroutineWithTimeout 和 WithCancel 控制单次 Redis 调用生命周期,超时立即返回错误,让上层决定降级(比如返回旧缓存或默认值)freecache)+ Redis 二级缓存,但要注意本地缓存失效一致性——简单场景用短 TTL + 主动刷新即可ctx 必须透传给所有 client.* 调用,否则请求被 Cancel 后,goroutine 仍可能卡在 Redis read 上。