redigo 高性能需正确配置连接池与命令模式:maxidle 设 20–50、minidleconns ≥5、idletimeout 30 分钟;批量操作用 send+flush+receive;所有操作必须带 context.withtimeout;键加服务前缀,序列化方式全局统一。

Redigo 不是开箱即用的高性能方案,直接调 redis.Dial 或裸用 conn.Do() 在高并发下必然掉帧、超时、连接耗尽——性能瓶颈几乎全出在连接池配置和命令调用模式上。
redigo.Pool 初始化必须显式设 MaxIdle、MinIdleConns 和 IdleTimeout
默认 MaxIdle=2、MinIdleConns=0,线上压测一上来就卡在 redis: connection pool timeout。这不是 Redis 慢,是连接池没水了。
-
MaxIdle设为 20–50:低于 20 容易排队;高于 50 可能打满 Redis 的maxclients(单实例建议 ≤5000) -
MinIdleConns必须 ≥5:防 SLB/NAT 网关静默断连,否则第一个请求必重连失败 -
IdleTimeout推荐30 * time.Minute:强制老化长连接,避免中间设备单向断开后 conn 还以为活着 - 初始化后立刻跑
rdb.Ping(ctx).Err(),别等第一个Get才暴露连不通
批量读写必须用 Send + Flush + Receive,别用循环里反复 Do
Do 是同步发—等—收,1000 次 GET 就是 1000 轮 RTT;而 Send+Flush 打包发出去,再统一 Receive,靠 Redis pipeline 把网络往返压到 1 次。
- 错误写法:
for i := range keys { conn.Do("GET", keys[i]) }—— QPS 直接砍掉 70% - 正确写法:循环调
conn.Send("GET", key),一次conn.Flush(),再循环conn.Receive() - 注意:所有
Send必须在Flush前完成,且Receive次数必须和Send次数一致,否则会错位读响应
所有 Redis 操作必须带 context.WithTimeout,禁用 context.Background()
HTTP handler 里传 context.Background() 给 client.Get,等于把 goroutine 生死交给 Redis 响应时间——它卡 5 秒,你的 handler 就卡 5 秒,监控看到的是 goroutine 数暴涨、QPS 断崖下跌。
- HTTP handler 中统一用:
ctx, cancel := context.WithTimeout(r.Context(), 300*time.Millisecond) - 写操作(
Set、Del、SET key val NX PX 1000)同样要超时,分布式锁写不进还不超时,后续请求全在空等 - 别在
init()里声明全局ctx = context.Background()—— 它没有 cancel 信号,根本不是“默认”,是“永生”
缓存键必须加服务前缀,结构体序列化方式必须全局统一
多个服务共用一个 Redis 实例但没前缀,或同一结构体在不同模块用 json.Marshal 和 gob.Encode 混用,结果就是缓存读出来 invalid character 或直接 panic,日志里找不到源头。
- 键格式建议:
svc:order:1001、svc:user:profile:456,冒号分层,服务名开头 - 结构体缓存统一走
json.Marshal+json.Unmarshal,避免gob的版本兼容陷阱 - 如果用
redis.String()解包,确保值一定是 string 类型,否则会 panic;不确定时先用redis.Bytes()再转
最常被跳过的其实是连接池初始化后的 Ping 验证和每个操作的 context 超时——它们不写在业务逻辑里,但一旦漏掉,故障就藏得深、恢复得慢。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











