必须显式配置PoolSize(20–50)、MinIdleConns(≥5)、MaxConnAge(30分钟),初始化后用带超时ctx调Ping验证连通性,所有操作须用context.WithTimeout而非Background,键加前缀且结构体序列化方式统一。

直接用 redis.NewClient() 初始化但不配参数、不验连通性、不设超时,线上一压就报 redis: connection pool timeout 或 goroutine 卡死——这不是 Redis 慢,是 Go 层配置没兜住。
初始化必须显式配 PoolSize 和 Ping 验证连通性
默认 PoolSize=10、MinIdleConns=0,高并发下连接池瞬间耗尽。冷启动时第一个请求还可能因空闲连接被 SLB 静默断开而失败。
-
PoolSize设为 20–50:QPS 超 300 就别用默认值;设太高(如 >100)可能打满 Redis 的maxclients(单实例建议 ≤5000) -
MinIdleConns必须 ≥5:防 NAT/SLB 断连后首请求重连失败 - 初始化后立刻用带超时的
ctx调rdb.Ping(ctx).Err(),别等第一个Get才暴露地址错或密码错 - 地址、密码、DB 从环境变量读,别硬编码
"localhost:6379"
所有操作必须带 context.WithTimeout,禁用 context.Background
在 HTTP handler 里传 context.Background() 给 client.Get(),等于把请求生命周期交给 Redis 响应时间——它卡 2 秒,你的 handler 就卡 2 秒,监控看到的是 goroutine 数暴涨、QPS 断崖下跌。
- HTTP handler 中统一用:
ctx, cancel := context.WithTimeout(r.Context(), 300*time.Millisecond) - 写操作(
Set、Del、分布式锁)同样要超时;锁逻辑缺超时,会导致后续请求永久等待 - 别在
init()里声明全局ctx = context.Background()——它没有取消信号,不是“默认”,是“永生”
缓存键必须加服务前缀,结构体序列化方式需全局统一
多个服务共用一个 Redis 实例但没前缀,或同一结构体在不同模块混用 json.Marshal 和 gob.Encode,结果就是读出来 invalid character 或直接 panic,日志里搜不到源头。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
立即学习“go语言免费学习笔记(深入)”;
- key 推荐格式:
"user:profile:123"、"order:summary:20260424:uid_789",前缀明确业务域 - 结构体必须字段导出 +
json:"field"tag,存取都走json.Marshal/json.Unmarshal - 拼 key 时避免裸接用户输入,先做
strings.ReplaceAll(username, ":", "_")
穿透/击穿/雪崩得在 Go 层兜底,Redis 自身不解决
靠 Redis 自带命令或配置扛不住这三类问题,必须在业务代码里加轻量策略。
- 穿透:查 DB 为空时,存
rdb.Set(ctx, key, "null", 60*time.Second);解包前判if val == "null" { return nil, nil } - 击穿:热点 key 过期瞬间大量请求打穿 DB,用
singleflight.Group包一层Do,同一 key 并发只放行一个回源 - 雪崩:TTL 加随机扰动,如
baseTTL + time.Duration(rand.Int63n(int64(2*time.Minute))),每次生成前用time.Now().UnixNano()做 seed
最易被忽略的点是:连接池参数和 context 超时不是“可选配置”,而是上线前必须验证的硬门槛;键设计和序列化方式看着琐碎,却是线上数据错乱的隐形推手——它们不出现在错误日志里,只在某次发布后某个接口突然返回空对象时才浮出水面。

















