JedisConnectionException Connection Reset

在使用redis的过程常见错误总结

1.JedisConnectionException Connection Reset

参考这边文章:

  1. Connection reset原因分析和解决方案

https://blog.csdn.net/cwclw/article/details/52797131

1.1问题描述

Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Connection reset
	at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:202)
	at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40)
	at redis.clients.jedis.Protocol.process(Protocol.java:151)
	at redis.clients.jedis.Protocol.read(Protocol.java:215)
	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
	at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:239)
	at redis.clients.jedis.BinaryJedis.set(BinaryJedis.java:211)
	at com.swtx.infrastructure.dataAccess.redis.RedisOperation.addCognitionLinkToRedis(RedisOperation.java:181)
	at com.swtx.domain.cognitron.sparkapi.CognitronAPI.addCognitionLinkToRedis(CognitronAPI.java:100)
	at com.swtx.domain.cognitron.sparkapi.CognitronAPI.discovery(CognitronAPI.java:82)
	at com.swtx.app.daimler.DaimlerLocalParallelTest_lipenghang.lambda$parallel$8(DaimlerLocalParallelTest_lipenghang.java:324)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1628)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:747)
	at java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:721)
	at java.util.stream.AbstractTask.compute(AbstractTask.java:316)
	at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool.helpComplete(ForkJoinPool.java:1870)
	at java.util.concurrent.ForkJoinPool.externalHelpComplete(ForkJoinPool.java:2467)
	at java.util.concurrent.ForkJoinTask.externalAwaitDone(ForkJoinTask.java:324)
	at java.util.concurrent.ForkJoinTask.doInvoke(ForkJoinTask.java:405)
	at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:734)
	at java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:714)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
	at java.util.stream.LongPipeline.reduce(LongPipeline.java:438)
	at java.util.stream.LongPipeline.sum(LongPipeline.java:396)
	at java.util.stream.ReferencePipeline.count(ReferencePipeline.java:526)
	at com.swtx.app.daimler.DaimlerLocalParallelTest_lipenghang.parallel(DaimlerLocalParallelTest_lipenghang.java:329)
	at com.swtx.app.daimler.DaimlerLocalParallelTest_lipenghang.parallelUpdate(DaimlerLocalParallelTest_lipenghang.java:233)
	at com.swtx.app.daimler.DaimlerLocalParallelTest_lipenghang.parallelTest(DaimlerLocalParallelTest_lipenghang.java:171)
	at com.swtx.app.daimler.DaimlerLocalParallelTest_lipenghang.main(DaimlerLocalParallelTest_lipenghang.java:128)
Caused by: java.net.SocketException: Connection reset
	at java.net.SocketInputStream.read(SocketInputStream.java:210)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at java.net.SocketInputStream.read(SocketInputStream.java:127)
	at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:196)
	... 33 more

Process finished with exit code 1

1.2该问题原因分析:

1.直接原因分析: 一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。简单的说就是在连接断开后的读和写操作引起的。

2.间接可能原因分析:

​ 多线程情况下,多个线程共用一个连接池中的连接,可能其他连接使用了其他线程正在使用的(或者关闭的连接对象)

1.3解决方法:

在使用连接池的时候,最好使用 try-catch-finally语句块关闭使用完成的redis连接(还回线程池),保证一个线程只处理一个socket连接;(放置异常的连接未关闭)

1.3.1配置连接池:

配置连接池
// 连接信息
private static final String HOST = "132.232.6.208";
private static final int PORT = 6381;

private JedisPoolConfig poolConfig = new JedisPoolConfig();
// 基本配置
poolConfig.setMaxTotal(1000);           // 最大连接数
poolConfig.setMaxIdle(32);              // 最大空闲连接数
poolConfig.setMaxWaitMillis(100*1000);  // 最大等待时间
poolConfig.setTestOnBorrow(true);       // 检查连接可用性, 确保获取的redis实例可用
                    
private static JedisPool jedisPool = new JedisPool(poolConfig, HOST, PORT);

1.3.2业务部分修改

public static void test02() {
        Jedis jedis = null;
        
        try {
            //jedisPool建议封装成工具类;并采用单例模式(桌静态对象)
            jedis = jedisPool.getResource();  // 获取Redus连接
            
            // 业务
            jedis.set("k1", "v111");
            System.out.println(jedis.get("k1"));
        }catch(Exception e){
            e.printStackTrace();
        } finally {
        	if(jedis != null){
             //jedisPool.returnResourceObject(jedis);  // 已废弃,推荐使用jedis.close()方法
        	 jedis.close(); // 关闭redis连接,还回redis连接池中;
        	}
        }
    }

其他相关redisPool连接参数解析:

https://www.cnblogs.com/forward22222/p/9601820.html

1.3.3正确使用方法:

package redistest.ml;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis 连接池工具
 */
public class JedisPoolUtil {

    private static final String HOST = "132.19.xxx.xxx";
    private static final int PORT = 6388;

    private static volatile JedisPool jedisPool = null;

    static {
        jedisPool = getJedisPoolInstance();
    }

    /**
     * 获取RedisPool实例(单例)
     * @return RedisPool实例
     */
    private static JedisPool getJedisPoolInstance() {
        if (jedisPool == null) {
            synchronized (JedisPoolUtil.class) {
                if (jedisPool == null) {

                    JedisPoolConfig poolConfig = new JedisPoolConfig();
                    poolConfig.setMaxTotal(1000);           // 最大连接数
                    poolConfig.setMaxIdle(32);              // 最大空闲连接数
                    poolConfig.setMaxWaitMillis(100*1000);  // 最大等待时间
                    poolConfig.setTestOnBorrow(true);       // 检查连接可用性, 确保获取的redis实例可用

                    jedisPool = new JedisPool(poolConfig, HOST, PORT);
                }
            }
        }

        return jedisPool;
    }

    /**
     * 从连接池中获取一个 Jedis 实例(连接),处理完业务员之后,还回连接池
     */
    public static void testRedis() {
        Jedis jedis = null;
        try {
            //jedisPool建议封装成工具类;并采用单例模式(桌静态对象)
            jedis = jedisPool.getResource();  // 获取Redus连接

            // 业务
            jedis.set("k1", "v111");
            System.out.println(jedis.get("k1"));
        }catch(Exception e){
            e.printStackTrace();
        } finally {
            if(jedis != null){
                //jedisPool.returnResourceObject(jedis);  // 已废弃,推荐使用jedis.close()方法
                jedis.close(); // 关闭redis连接,还回redis连接池中;
            }
        }
    }

}

2.jedis 的 Unexpected end of stream异常问题

参考这个https://blog.csdn.net/xiao__jia__jia/article/details/96011509

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章