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

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