去发现生活中的美好,记录生活中的点点滴滴

Redis间歇性连接超时排查记录

linux admin 93℃

最近发现服务器redis不稳定,经常连接超时,开始查redis日志,初步分析,可能存在以下情况:
1、网络资源耗尽;
2、连接数用完了;
3、端口TCP backlog队列满了(linux内核参数somaxconn(每一个端口最大的监听队列数)和redis TCP_backlog(redis设置端口最大监听队列数));
4、网络延迟;

1、网络问题,这个由于服务器之间是内网访问,服务器网络资源一直很稳定,并没有出现波峰的情况,首先排除这个,网络延迟,经过测试也排除;

延迟测试:redis-cli -h {host} -p {port} --latency
采样延迟测试:redis-cli -h {host} -p {port} --latency-history 默认15s一次
图形线上测试结果:redis-cli -h {host} -p {port} --latency-dist
使用--latency选项,cli将运行一个循环,将PING命令发送到Redis实例,并测量响应时间,每秒发送100次,统计时间以毫秒为单位。
使用--latency-history选项,每15秒新的采样会重新开始。
使用--latency-dist选项,使用彩色终端显示一系列延时特征。
使用--intrinsic-latency选项,将会检查cli客户端所在机器的延迟,即操作系统内核的延迟,后面为固有检查时间,一般100即可。

2、redis连接数用完,这个有可能,下面一步步排查:

首先排查redi日志,发现有两个错误:

WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

基于以上两个方向,接下来排查TCP time wait情况:

ss -s
ss state all dport = :6379
ss -anp
或者
netstat -ant|awk '/^tcp/ {++S[$NF]} END {for(a in S) print (a,S[a])}'
netstat -an | awk '/^tcp/ {++State[$NF]}END{for(key in State)print key "\t" State[key]}'
或者
netstat -an |grep TIME_WAIT|wc -l 
netstat -an | grep 6379 | grep EST | wc -l 

发现TCP 有大量time wait和ESTABLISHED的连接,到这里可以初步确定是连接不够用了;
(ESTABLISHED的意思是建立连接。表示两台机器正在通信。 TIME_WAIT的产生条件:主动关闭方在发送四次挥手的最后一个ACK后会变为TIME_WAIT状态,持续时间为2MSL,Linux中一个MSL是30秒,是不可配置的,这里是服务端主动调用close()断开连接,收到客户端确认后状态变为TIME_WAIT)

微信截图_20210318112102

如果TIME_WAIT过多可以修改以下参数:

sysctl -w net.ipv4.tcp_max_tw_buckets=180000
sysctl -w net.ipv4.tcp_tw_recycle=1

接下来查redis.conf

vim /etc/redis.conf

可以看到redis的tcp-backlog 511,511是redis默认配置,也就是TCP监听的最大队列数,一般这个设置要比内核somaxconn要小,

more /proc/sys/net/core/somaxconn 

linux内核参数默认值一般是128(定义了系统中每一个端口最大的监听队列的长度),对于负载很大的服务程序来说大大的不够。一般会将它修改为2048或者更大,可以通过root用户改为

echo 2048 > /proc/sys/net/core/somaxconn

同时,为了保证重启后生效,在/etc/sysctl.conf中添加如下

net.core.somaxconn = 2048

终端执行

sysctl -p

然后,进入redis-cli模式,输入

info clients

查到connected_clients连接有100多个,进而查看有哪些IP占用这些连接:

client list

可以看到是哪些IP大量占用了redis没释放连接;

经过排查,有一部分是常驻进程,没法释放,有一部分是连接后没有进行close释放,比如try catch 抛出异常后没有处理close,比如慢查询(包括 mysql慢查询)因素导致占用连接等等

第二个问题,翻译过来是
警告:您的内核中启用了透明大页面(THP)支持。这将导致Redis的延迟和内存使用问题。要解决此问题,请以root用户身份运行命令“echo never>/sys/kernel/mm/transparent_hugepage/enabled”,并将其添加到/etc/rc.local中,以便在重新启动后保留设置。禁用THP后,必须重新启动Redis

按照提示解决即可:

echo never > /sys/kernel/mm/transparent_hugepage/enabled
如果要永久的话,需要写入/etc/rc.local

至此,redis超时问题解决。

转载请注明:永盟博客 » Redis间歇性连接超时排查记录

喜欢 (2)