go-redis连接池过小致高并发超时,需设PoolSize=QPS×RT×2并配MinIdleConns;SetNX锁须带过期时间、用随机value及Lua校验解锁;Pipeline禁用WATCH/EXEC等命令,大体积数据需分批;v9版强制context、Protocol适配及健康检查。

go-redis 连接池设置不合理导致超时
默认连接池太小,高并发下 context.DeadlineExceeded 错误频发,不是 Redis 慢,是客户端卡在等连接。
-
opt.PoolSize建议设为 QPS × 平均 RT(秒)× 2,比如 1000 QPS、平均耗时 5ms,至少配PoolSize: 10 - 别漏掉
opt.MinIdleConns,否则空闲连接会被回收,突发流量来临时又要重建连接 - 如果用的是
redis.NewClient,记得传入完整配置结构体,直接改client.Options()不生效
用 SetNX 实现分布式锁却没加过期时间
SET key value NX 本身不带过期逻辑,忘设 EX 或 PX,锁一旦没释放就永久卡死。
- 必须用
SetNX(ctx, key, value, time.Second*10),第四个参数是time.Duration,不是毫秒整数 - value 推荐用随机字符串(如
uuid.NewString()),避免误删别人持有的锁 - 解锁不能只用
DEL,得用 Lua 脚本校验 value 再删,否则可能删错——eval("if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end", []string{key}, []string{value})
Pipeline 批量写入时 panic: "command is not supported"
不是所有命令都支持 pipeline,比如 WATCH、EXEC、PUBLISH 在 client.Pipeline() 里会直接 panic。
- 只对纯读写命令用 pipeline:
SET、GET、HGETALL、ZRANGE等安全 - 遇到
redis.Nil错误别急着重试,pipeline 中某个命令失败不会中断后续,但返回值顺序和命令顺序严格对应,要按索引取结果 - 大体积数据批量写建议分批,单次 pipeline 超过 1000 条容易触发 Redis 的
client-output-buffer-limit限制
Go module 引入 v9 版本后 DialContext 报错
v9 开始强制要求 context,老代码里直接传 nil 会 panic,且 redis.Options 结构体字段名有变更。
立即学习“go语言免费学习笔记(深入)”;
- 连接必须用
redis.NewClient(&redis.Options{Addr: "localhost:6379"}),不再接受地址字符串参数 - 所有命令调用前补上 context,比如
client.Get(ctx, "key").Result(),没有 ctx 就编译不过 - v9 默认启用
Protocol: redis.ProtocolVersion3,如果服务端是 Redis 6 以下,得显式设Protocol: redis.ProtocolVersion2
最常被跳过的其实是健康检查:上线前没跑 client.Ping(ctx).Err(),或只在初始化时测一次。连接可能中途断开,而 go-redis 不自动重连——得自己套一层重试或监听 client.Conn().Close() 事件。


















