问题来源
高峰盯盘期间,通过kibana查询发现不定时存在一些redis慢查询日志(客户端日志);而且目前项目中记录redis慢查询日志的门限默为300ms。这种不知原因且不定时的慢查询是非常危险的。
注1:redis server实例配置的slow log门限为10ms,并且存在慢查询报警。
注2:客户端与redis之间还存在Twemproxy代理(以下简称tw)。
注2:客户端为Golang服务,与tw之间是长连接,基于连接池实现。
【案例1】客户端问题排查
2020.07.29 18:19:21左右, 出现一小波redis慢查询日志。
分析表明:
- redis并没有慢查询报警;
- tw监控表明当时请求的ops没有明显变化;
- 客户端同时刻所有的慢查询日志都在一台机器;
- tw与redis监控的cpu负载等指标没有明显异常;
- tw客户端连接数同时刻有突增;
结合以上现象有以下几个怀疑点:
1)tw代理导致的慢查询?那这样同时刻的慢查询应该比较均匀的分布到多台客户端机器,只存在一台机器并不是很合理;
2)redis连接池导致的,连接池通常会存在最大连接数的限制,而tw监控表明客户端连接数同时刻存在突增情况;
项目中redis客户使用的是 github.com/go-redis/redis ,连接池相关配置定义在redis.Options结构:
type Options struct {
PoolSize int
//连接池大小,即最大连接数
PoolTimeout time.Duration
//获取连接超时时间,当连接池所有连接都被占用,最大等待时间;
//默认为ReadTimeout+1秒
IdleTimeout time.Duration
//连接空闲超时时间,长时间空闲的连接会被客户端主动释放;
}
可能『卡住』的地方就是获取连接了,代码逻辑参照pool.(*ConnPool).Get:
select {
case p.queue <- struct{}{}:
default:
timer := timers.Get().(*time.Timer)
timer.Reset(p.opt.PoolTimeout)
select {