Redis客户端周期性出现connect timeout

1、背景:

大部分互联网公司都会有Mysql或者Oracle的DBA,可是在Nosql方面通常不会设置专门的DBA。不过对于一些知名的互联网公司来讲,Nosql的使用量是巨大的,因此一般让Mysql的DBA或者单独聘请工程师来维护一些Nosql数据库,好比:java

Redis, Hbase, Memcache(其实严格讲不是nosql), Mongodb, Cassandra。从讲座看美团网应该是有专职的Redis DBA。因此做为业务开发人员不须要本身安装、配置、运维Redis,只须要找Redis DBA来申请就能够了。mysql

这里为了简化说明:Redis DBA提供的服务叫作Redis云,业务开发人员叫作业务端(redis的使用者)redis

2、现象

业务端在使用redis云提供的redis服务后,常常出现connect timeout:sql

#java代码
redis.clients.jedis.exceptions.JedisConnectionException  
java.net.SocketException  
java.net.SocketTimeoutException:connect time out

3、分析和怀疑:

业务端通常认为redis出现问题,就是redis云有问题,人的“正常”思惟:看别人错误容易,发现本身难,扯多了, 出现这个有不少缘由:数据库

   (1). 网络缘由:好比是否存在跨机房、网络割接等等。服务器

   (2). 慢查询,由于redis是单线程,若是有慢查询的话,会阻塞住以后的操做。 网络

   (3). value值过大?好比value几十兆,固然这种状况比较少,其实也能够看作是慢查询的一种运维

   (4). aof重写/rdb fork发生?瞬间会堵一下Redis服务器。nosql

   (5). 其余..................tcp

4、查询缘由

演讲者一开始怀疑是网络问题,可是并未发现问题,观察各类对比图表,tcp listenOverFlow和timeout常常周期出现。(赞一下这个监控,咱们监控如今尚未这个层面的)

有关listenOverFlow:

查看现有的链接数是否大于设置的backlog,若是大于就丢弃,并相应的参数值加1。其中backlog是由程序和系统参数net.core.somaxconn共同设置,当backlog的值大于系统设置的net.core.somaxconn时则取net.core.somaxconn的值,不然取程序设置的backlog值。这种出错的方式也被记录在TcpListenOverflows中(其只记录了链接个数不足而产生溢出错误的次数!)。

以为可能和TCP相关,因而分析了Tcp三次握手:最后一次握手客户端的请求会进入服务器端的一个队列(能够认为是下三图)中,若是这个队列满了,就会发生上面的异常。(accept)

  (1) TCP三次握手: 

  (2) redis客户端与redis服务器交互的过程(本质就是TCP请求)

  (3) I/O 多路复用程序经过队列向文件事件分派器传送套接字的过程

 (4) 和redis有什么关系呢?

因为Redis的单线程模型(对命令的处理和链接的处理都是在一个线程中),若是存在慢查询的话,会出现上面的这种状况,形成新的accept的链接进不了队列。

 5、解决方法:

一、对慢查询进行持久化,好比定时存放到mysql之类。(redis的慢查询只是一个list,超过list设置的最大值,会清除掉以前的数据,也就是看不到历史)

二、对慢查询进行报警(频率、数量、时间)等等因素

三、其实应该作的是:对业务端进行培训,告诉他们一下redis开发的坑,redis不是万金油,这个和Mysql DBA要培训Mysql使用者同样,不然防不胜防。好比他执行了 monitor, keys *, flushall, drop table, update table set a=1; 这种也是防不胜防的(固然也能够作限制,利用rename-command一个随机数),可是提升工程师的水平才是关键。

相关文章
相关标签/搜索