RedisClient 报出java.net.SocketException: Broken pipe异常

问题场景:

读写数据量小时没有问题,当读写数据量大的时候偶尔会报出这个异常

原因分析:大数据操作时间较长,被redis server强行close了,超过redis server的某个值。

相关参数:minEvictableIdleTimeMillis 。线程中如果检测到当前连接的最后活跃时间和当前时间的差值大于
minEvictableIdleTimeMillis,则关闭当前连接

其他案例:

在方案三上线以后,我认为这些redis应该会消停了,redis运行一段时间后,的确再也没用timeout exception了,但是在运行一段时间后,tpn在向redis执行请求时,往redis写入命令时会报这个异常:
java.net.SocketException: Broken pipe。我们知道,如果一个socket连接已经被远端给close掉了,但是客户端没有察觉,仍然通过这个连接读写数据,那么就会产生Broken pipe异常。因为tpn使用jedis,通过common pool来实现jedis的connection pool,我第一反应就是tpn没用正确使用jedis的connection pool,没有销毁掉broken的redis connection,而是已经重新把归还给了connection pool,或者是jedis的connection  pool有bug,造成了connection泄露,导致ton在往一条已经往一条已经被close的连接写入数据。但是仔细检查了一遍tpn的代码和jedis connection pool的代码,发现没用什么问题,那就说明有些redis是真的被redis服务端给关闭了,但是jedis 的connection pool没有发现。
     因为客户端的jedis pool没有问题,那么基本上可以确定的确是redis server端关闭了一些连接。首先怀疑的就是tpn的redis 配置出错了,错误地配置了redis.conf里的timeout 配置项:
首先怀疑的是不是tpn的redis配置不多,造成因此就去查看redis的相关代码。redis的配置文件redis.config里面有timeou这个配置项:
          # Close the connection after a client is idle for N seconds (0 to disable)          timeout 0
   检查了下tpn 6台redis上的所有配置文件,发现都没有配置这个选择,但是tpn部署了两个版本的redis,redis-2.6.14和redis-2.4,结果在redis-2.4里面,如果没有配置这个值,redis就会使用默认的值,5*60(s),而redis-2.6.14的默认值是0,即disable timeout,同时又去查看了下jedis common pool的设置,发现minEvictableIdleTimeMillis=1000L * 60L * 60L * 5L(ms),即一个redis连接的空闲时间超过5个小时才会被connection pool给回收。很明显,就是因为客户端和服务端的connection idle time设置不一样,造成了connection被一端关闭了,但是另一端没有感知,所有造成了broken pipe。解决办法就是把redid-2.4升级到redid-2.6.14。
 

你可能感兴趣的:(Redis)