redis client list实战记录

一、redis client list各参数的含义

连接一个测试的redis服务,执行client list命令,得到的输出如下:

[work@q]$ redis-cli -h 127.0.0.1 -p 6379 client list 
id=618509 addr=xx:24514 fd=9 name= age=11 idle=11 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=info
id=618514 addr=xx:51426 fd=10 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client

各参数的含义如下:

参数含义
id客户端连接id
addr客户端连接IP和端口
fdsocket的文件描述符
name客户端连接名
age客户端连接存活时间
idle客户端连接空闲时间
flags客户端类型标识
db当前客户端正在使用的数据库索引下标
sub/psub当前客户端订阅的频道或者模式数
multi当前事务中执行的命令个数
qbuf输入缓冲区总容量
qbuf-free输入缓冲区剩余容量
ob1固定缓冲区的长度
oll动态缓冲区列表的长度
omem固定缓冲区和动态缓冲区使用的容量
events文件描述符事件(r/w)
cmd当前客户端最后一次执行的命令,不包含参数

二、实战记录

2.1 发现问题

监控突然报警,提示客户端连接太多,查看监控后,发现果然是这样。

登录服务器,使用client list查看连接的客户端情况,发现很多如下的客户端连接

id=29018917 addr=?:0 fd=6693 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=NULL

这些连接并不是我们平时看到的比较正常的那种连接,比如addr=?:0,这是什么鬼?还有age=0,idle=0,cmd=NULL又是什么意思,age=xxx,idle=xxxx,cmd=NULL还是见过的,那这种=0表示几个意思?

2.2 确定问题

查资料后得知,只要是ageidle的数字一样就表示空闲连接,后面的数字是时间,也就是说,age=0,idle=0,也表示空闲连接,而且是刚建立好的空闲连接。

现在知道age=0,idle=0表示刚建立好的空闲连接,那addr=?:0表示啥呢?

Google和百度都没找到这个是啥意思,去翻了下源码:

 * On failure the function still populates 'peerid' with the "?:0" string
 * in case you want to relax error checking or need to display something
 * anyway (see anetPeerToString implementation for more info). */
int genClientPeerId(redisClient *client, char *peerid, size_t peerid_len) {
    char ip[REDIS_IP_STR_LEN];
    int port;

    if (client->flags & REDIS_UNIX_SOCKET) {
        /* Unix socket client. */
        snprintf(peerid,peerid_len,"%s:0",server.unixsocket);
        return REDIS_OK;
    } else {
        /* TCP client. */
        int retval = anetPeerToString(client->fd,ip,sizeof(ip),&port);
        formatPeerId(peerid,peerid_len,ip,port);
        return (retval == -1) ? REDIS_ERR : REDIS_OK;
    }
}

可以看到,这个表示的意思是:如果获取客户端的ip:port失败,该函数就使用“?:0”字符串填充“peerid”。

知道这两个是什么意思之后,就该想办法解决这个问题了。

2.3 解决问题

其实这个问题主要就是大量的空闲连接的问题,也就是age=xxxx=idle的问题。

主要分为以下两种情况:

  • age=xxxx1,idle=xxxx2:这种情况(xxxx1=xxxx2),表示建立了大量的空闲连接,且很长时间都还没有释放。
    这种比较好解决,通过config get timeout xx(单位为s)设置timeout,就可以将长时间的空闲连接释放掉。
  • age=0,idle=0:这种比较少遇到,表示刚建立的连接。如果执行client list几次,发现都是这样的情况,那就得提高警惕了。
    可能是客户端的代码有bug,疯狂建立连接后又释放,或者是遭到攻击了。得重启客户端程序或者其他操作,服务端好像没啥办法可以解决,,,(知道的可以留言赐教)

以上两种情况一般都会伴随着cmd=NULL(也就是最后一次没有执行什么命令),比较容易鉴别出来。

三、总结

单节点内存使用率上涨,响应时间慢,同时连接数很高的情况,很可能是因为客户端连接数过多,redis服务端输入缓冲区过大,才导致内存使用量上涨的,应该着重解决客户端连接问题,而不是内存上涨问题。

这时候应该使用client list查看连接的客户端都是些什么地址,存活时间和空闲时间,以及执行的命令,分析一下客户端是否是正常的。

四、扩展思考

4.1 为什么切库之后,主从不能正常建立连接,进行复制?

(新主从为send_bluk状态,新从库连接状态为down)

因为切库之后,新主库马上被连接打满,阻塞了,来不及和新从库做主从复制。

主库也还没来得及释放连接,age=xxxx idle=xxxx,需要
设置timeout 60释放连接。此时会剩下cmd=CLUSTER的连接,应该是获取集群信息的命令,可能是cluster solts或者其他的(当时忘记记录是什么地址了,所以不好推测)。

4.2 从库挂了之后,主库内存突然升高,之后又回落

很可能是因为从主从复制的输出缓冲区过满,主库本来要发给从库的数据一直没有被消费,所以感觉阻塞了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值