必须配置 PoolSize 和 Timeout,PoolSize 按 QPS×平均响应时间×1.5 并向上取整(如设为 16),Timeout 推荐 5s;所有操作须传带超时的 context,禁用 context.Background() 和 TODO();结构体存前需 json.Marshal;穿透用空值占位,雪崩用随机 TTL。

直接用 redis.NewClient 初始化,配好 PoolSize 和 Timeout,所有操作带 context.Context,别碰 redis.Conn —— 这是当前生产环境唯一靠谱的起点。
redis.NewClient 初始化必须配哪些 Options
不设 PoolSize 和 Timeout 就等于裸奔,线上一压就出 read tcp ... i/o timeout 或 too many open files。默认 PoolSize=10、Timeout=0(无限等待),根本扛不住真实流量。
-
PoolSize:按 QPS × 平均响应时间 × 1.5 算,比如 200 QPS × 0.04s × 1.5 ≈ 12 → 实际设 16 更稳 -
Timeout:必须设,推荐5 * time.Second;HTTP handler 里更得用context.WithTimeout(r.Context(), 800*time.Millisecond) -
MinIdleConns:设为PoolSize / 2,防冷启动首请求慢 -
MaxConnAge:设30 * time.Minute,避免 NAT/防火墙静默断连 -
Password和DB按实际填,空密码留空字符串,别传nil
Set/Get 必须传 context,且不能用 context.Background()
所有 client.Set()、client.Get() 第一个参数必须是带生命周期控制的 context.Context。硬写 context.Background() 是定时炸弹:用户关页面、API 超时、K8s probe 失败,你的 Redis 请求还在后台死等。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- HTTP handler 中:用
ctx, cancel := context.WithTimeout(r.Context(), 500*time.Millisecond),然后 defer cancel() - 别用
context.TODO()占位,它只是开发期兜底,不是生产选项 - 如果要重试,用
backoff.Retry+context.WithDeadline控制总耗时,别 for 循环硬等 - 结构体存缓存前必须
json.Marshal,Redis 不认 Go 类型,直接传 struct 会存成空字符串
缓存穿透和雪崩的 Go 层应对逻辑
Redis 自身不解决穿透和雪崩,得在 Go 代码里加一层判断和扰动。否则上线后 DB 瞬间被打垮,不是 Redis 的锅,是你没拦住。
立即学习“go语言免费学习笔记(深入)”;
- 穿透防护:查
client.Get(ctx, key)返回redis.Nil时,不要直连 DB,先client.Set(ctx, key, "null", time.Minute)占位;业务层解包时判断if val == "null" { return nil, nil } - 雪崩防护:TTL 别写死,比如
10 * time.Minute;改成baseTTL + time.Duration(rand.Int63n(int64(3*time.Minute))) - 随机数种子别在全局 init 里初始化,
rand.Seed(time.Now().UnixNano())已弃用;每次 Set 前用rand.New(rand.NewSource(time.Now().UnixNano())) - 别自己手写 SETNX 布隆过滤器,小项目用空值占位 + 短 TTL 更简单可控
最常被忽略的是:连接验证只做 Ping() 不够,得测读写通路;还有就是 client.Close() 只需在进程退出前调一次,别在每次请求后乱 Close。

















