先上问题:

redis.clients.jedis.exceptions.JedisConnectionException: Attempting to read from a broken connection
	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:274)
	at redis.clients.jedis.Connection.getIntegerReply(Connection.java:220)
	at redis.clients.jedis.Jedis.exists(Jedis.java:213)
	at com.cmcc.message.util.JedisUtil.existKey(JedisUtil.java:138)
	at com.cmcc.message.util.TokenUtil.getTokenConfig(TokenUtil.java:35)
	at com.cmcc.message.consumer.SmsConsumer.process(SmsConsumer.java:68)
	at com.cmcc.message.consumer.SmsConsumer$$FastClassBySpringCGLIB$$8503f9d5.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

jedis配置代码:

@Configuration
public class JedisClusterConfig {
    
    private static RedisProperties redisProperties;
    
    private static Jedis jedisCluster = null;
    
    @Autowired
    private RedisProperties redisProperties2;
 
    @PostConstruct
    public void init() {
        redisProperties = redisProperties2;
        if (jedisCluster==null) {
            try {
                jedisCluster = reloadJedisCluster();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 获取JedisCluster对象
     * 
     * @return
     * @throws Exception
     */
    public static Jedis getCluster() throws Exception {
        if (jedisCluster == null) {
            synchronized (JedisClusterConfig.class) {
                jedisCluster = reloadJedisCluster();
            }
            return jedisCluster;
        } else {
            return jedisCluster;
        }
    }
    
//    public static JedisCluster getJedisCluster(){
//        String [] serverArray=redisProperties.getClusterNodes().split(",");
//        Set<HostAndPort> nodes=new HashSet<>();
//
//        for (String ipPort:serverArray){
//            String [] ipPortPair=ipPort.split(":");
//            nodes.add(new HostAndPort(ipPortPair[0].trim(),Integer.valueOf(ipPortPair[1].trim())));
//
//        }
//        String redisAuthPass = redisProperties.getRedisAuthPass();
//        return  new JedisCluster(nodes,2000, 2000, 6, redisAuthPass, new JedisPoolConfig());
//    }
    
    private static Jedis reloadJedisCluster() throws Exception {
        System.out.println("初始化实体");	
        Jedis cluster = null;
        String redisAuthPass = redisProperties.getRedisAuthPass();
        String addrs = redisProperties.getClusterNodes();
        String [] ipPortPair=addrs.split(":");
        HostAndPort node = new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim()));
        cluster = new Jedis(node);
        cluster.auth(redisAuthPass);
        return cluster;
    }

猜测原因:

多线程请求redis获取内容,线程数>2就会报这个错误,百度了一下这个问题,没找到很好的解答。

初步猜测是因为没有使用jedispool,又没有释放连接导致,尝试更新为jedispool。

@Configuration
public class RedisConfig extends CachingConfigurerSupport {
 
    protected static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
 
    @Value("${spring.redis.host}")
    private String host;
 
    @Value("${spring.redis.port}")
    private int port;
 
    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxTotal;
 
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
 
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;
 
    @Value("${spring.redis.password}")
    private String password;
 
    @Value("${spring.redis.timeout}")
    private int timeout;
 
    public JedisPool redisPoolFactory() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(maxTotal);
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        JedisPool jedisPool = null;
        if(password == null || password.equals("")){
            jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout);
        }else{
            jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout,password);
        }
        logger.info("JedisPool注入成功!!");
        logger.info("redis地址:" + host + ":" + port);
        return jedisPool;
    }
}

经测试,报错没再出现。

后续又查看了jedisCluster的源码,发现jediscluster默认可以实现连接池。

遗留问题:

  1. jedis连接默认释放时间是多少?为什么并发情况下会出现这种异常
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐