Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException:

问题:
java链接不上redis。

异常信息:
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed outjava

 

package com.redis;

import redis.clients.jedis.Jedis;

public class HelloRedis {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		Jedis jedis = new Jedis("192.168.144.130", 6379);
		jedis.set("java", "http://www.baidu.com");
		String value = jedis.get("java");
		System.out.println(value);

	}

}

 当 咱们获取链接后对redis进行操做时,抛出 redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out异常。redis

异常代码以下:服务器

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out并发

at redis.clients.jedis.Protocol.process(Protocol.java:79)
at redis.clients.jedis.Protocol.read(Protocol.java:131)
at redis.clients.jedis.Connection.getIntegerReply(Connection.java:188)
at redis.clients.jedis.Jedis.sismember(Jedis.java:1266)
socket

这是一个比较麻烦的异常,困扰了我一天的时间。咱们都知道Redis是对内存进行操做,速度应该都在毫秒级,这是咱们一般的认识,因此当对Redis操做出现几秒的超时时间,你能想象吗?
咱们仍是先分析一下Jedis的源代码吧,以sadd操做为例:
post

  1. public Long sadd(final String key, final String... members) {
  2. checkIsInMulti();
  3. client.sadd(key, members);
  4. return client.getIntegerReply();
  5. }

client是redis.clients.jedis.Client.java的实例,继承关系以下:
public class Client extends BinaryClient implements Commands;
性能

public class BinaryClient extends Connection;spa

Connection 包装了对Redis server的socket操做,命令写操做经过socket.getOutputStream()输出流将命令信息发送到redis server,当写完命令后要经过socket.getInputStream()的到的输入流将
命令执行结果返回,这中间必然会有一个命令执行到结果返回的延时时间,这就是一个Jedis调用redis命令操做所用的时间。
.net

须要说明的是,Redis server是单线程执行全部链接发送过来的命令的,也就是说无论并发中有多少个client在发送命令,redis-server端是单线程处理的,并按照默认的FIFO方式处理请求,线程

这个可在redis.conf配置文件中配置。关于redis server的详细运行机制参见:http://redis.io/documentation

所 以client.sadd(key, members);调用完后只是将命令信息发送到了redis server端,具体有没有执行要看redis server的负载状况。而后,经过client.getIntegerReply();等待(time out)返回结果。
Connection初始化socket时有多种选择,其中设置socket time out 的方法以下:

  1. public void rollbackTimeout() {
  2.           try {
  3.             socket.setSoTimeout(timeout);
  4.             socket.setKeepAlive(false);
  5.           } catch (SocketException ex) {
  6.             throw new JedisException(ex);
  7.           }
  8.       }

由redis.clients.jedis.Protocol.DEFAULT_TIMEOUT = 2000 咱们知道默认的超时时间是2秒,这个时间相对于redis操做内存毫秒级的速度来讲已经很长,那咱们为何还会遇到
ava.net.SocketTimeoutException: Read timed out异常呢?redis操做内存虽然平均毫秒级的,但当数据量很大时未必都如此快速。在个人开发过程当中就遇到过一个集合到了

千万级数据量,一次操做超时时间在秒级是很正常的,并且机器性能很好的状况下已经如此,更况且咱们本机开发的机器相对于生产服务器来讲速度会更慢了。因此在初始化JedisPool时应该根据实际

状况经过redis.clients.jedis.JedisPoolConfig合理设置链接池参数,经过edisPool构造方法,合理设置socket读取输入InputStream的超时时间。

 

  1. pool = new JedisPool(config, host, port, 100000);

 

注意第四个参数time out,设置成咱们能容忍的超时时间,单位是毫秒。但不知道为何既然单位是毫秒,为何参数类型是int而不是long。

设置第四个参数后,我在四千万数据量集合上操做最多一次大概超时5秒,问题基本解决。