Go应用Redis连接池需设PoolSize为并发请求数2–4倍并Ping验证,禁用context.Background,空值缓存用"null"+随机TTL防穿透,结构体序列化须导出字段加json tag,集群/哨兵须动态配置地址。
直接用 redis.newclient 初始化再调 set/get 是能跑通,但上线后大概率遇到连接耗尽、超时卡死、缓存穿透打垮 db、反序列化为空对象等问题——根本原因不是 redis 不行,而是 go 层没管好连接生命周期、上下文、序列化和过期策略。
初始化 client 必须设 PoolSize 和 Ping 验证
默认的 redis.NewClient 虽带连接池,但 PoolSize 是 10,小流量没问题;QPS 上千时会频繁阻塞在 pool.Get,报 redis: connection pool timeout。更糟的是,不主动 Ping(),首次 Get() 失败才暴露连不上 Redis。
-
PoolSize建议设为预估并发请求数的 2–4 倍(例如 QPS 200,设 40–80),但不超过 Redis 的maxclients(默认 10000) - 必须在
init()或启动阶段用带超时的ctx调rdb.Ping(ctx).Err(),别等线上才发现配置错了 - 别在 handler 里用
context.Background()—— 所有操作都该复用 request context 或至少加WithTimeout - 进程退出前务必调
rdb.Close(),否则 fd 持续增长,最终触发too many open files
缓存穿透:空值 + 随机 TTL 是最简兜底
用户查一个永远不存在的 user_id=999999999,缓存没命中,DB 也没数据,下次还来——这就是穿透。redis.Nil 返回后直接查 DB 是危险的,得在 Go 层拦截。
- 查缓存返回
redis.Nil时,不要立刻查 DB,先rdb.Set(ctx, key, "null", baseTTL+jitter),值固定用字符串"null" -
jitter必须每次生成:用rand.New(rand.NewSource(time.Now().UnixNano())),不能全局复用 seed,否则重启后所有 key 还是同时过期 - 业务层读到
"null"要显式判断:if val == "null" { return nil, nil },不然会当成真实数据解包 - 别一上来就上布隆过滤器——小项目空值缓存 + 短 TTL(如 1–2 分钟)更可控
结构体存 Redis:只用 json,且字段必须导出+带 tag
直接 json.Marshal(user) 存进去,json.Unmarshal([]byte(val), &user) 读出来却是空对象?八成是 struct 字段没导出或缺 json: tag。
- 字段名必须首字母大写(Go 可导出),且显式加 tag:
ID int `json:"id"`,否则json包跳过该字段 - 禁用
gob—— 它只认 Go 进程,跨语言(Python/Node.js)或未来服务拆分后直接反序列化失败 - 存之前先
json.Marshal试一下,检查是否报错,能提前发现 struct 定义问题 -
time.Time别直接塞:统一转成int64时间戳再存,避免 JSON 默认 RFC3339 字符串和 gob 存纳秒整数的解析不一致
集群/哨兵部署不能硬写 localhost:6379
本地开发用单节点没问题,但生产环境基本都是 Redis Cluster 或哨兵。硬编码 "localhost:6379" 在容器或 K8s 下必然连不上,且单节点客户端不感知故障转移。
- Redis Cluster 用
redis.NewClusterClient,传入至少 2–3 个 seed node 地址(如[]string{"redis-0:7000", "redis-1:7000"}) - 哨兵模式用
redis.NewFailoverClient,必须显式传MasterName和全部哨兵地址列表,漏一个都会初始化失败 - 所有客户端建议加
MinIdleConns: 5和MaxConnAge: 30 * time.Minute,防止连接老化被中间设备(如 SLB)静默断开 - 地址来源从代码移出,走环境变量或配置中心(如
os.Getenv("REDIS_ADDRS")),别埋死值
真正难的不是写对一行 rdb.Set,而是每个 ctx 是否带超时、每个 json.Unmarshal 是否检查 error、每个 Set 的 TTL 是否加了 jitter、每个 client 初始化是否验证了连接——这些细节不落地,分布式缓存就只是个看起来能跑的 demo。


















