波神

导航

解决Jedis链接报超时异常和connection reset异常的方法

一、链接池配置

  <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
     <!-- ${redis.max_total:64}会优先查找是否已经配置redis.max_total的属性,如果没有配置,则为64   -->
    <property name="maxTotal" value="${redis.max_total:300}" />
    <property name="maxIdle" value="${redis.max_idle:8}" />
    <property name="maxWaitMillis" value="${redis.max_wait_millis:30000}" />
    <property name="testOnBorrow" value="true" />
  <!-- whenExhaustedAction为1表示当链接池的实例用完时,阻塞,直到有可用链接资源   -->
    <property name="blockWhenExhausted"  value="true"></property> 
  </bean>

  <bean id="jedisSentinelPoolConfig" class="com.chinacloud.monitoring.api.util.JedisSentinelPoolConfig">
    <constructor-arg index="0" value="${redis.master.name}" />
    <constructor-arg index="1" value="${redis.sentinels}" />
    <constructor-arg index="2" ref="jedisPoolConfig" />
  </bean>

  <bean id="jedisHelper" class="com.chinacloud.monitoring.api.util.JedisHelper" destroy-method="destroy">
    <!--对应于JedisHelper类里面的的构造函数   -->
    <constructor-arg index="0" ref="jedisSentinelPoolConfig" />
  </bean>

二、JedisSentinelPoolConfig类

package com.chinacloud.monitoring.api.util;

import java.util.HashSet;
import java.util.Set;

import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

public class JedisSentinelPoolConfig {
    //在集群中的主机maste-slave模式下
    private String masterName;
    private String sentinels;
    private JedisPoolConfig jedisConfig;

    public JedisSentinelPoolConfig(String masterName, String sentinels, JedisPoolConfig jedisConfig) {
        //TODO: validation
        this.masterName = masterName;
        this.sentinels = sentinels;
        this.jedisConfig = jedisConfig;
        
    }

    //JedisSentinelPool支持集群的链接池
    public JedisSentinelPool getJedisSentinelPool() {
        String[] sentinelstrs = sentinels.split(",");
        Set<String> sentinelsSet = new HashSet<String>(sentinelstrs.length);
        for (String st : sentinelstrs) {
            sentinelsSet.add(st);
        }
        //30000表示超时为30秒
        return new JedisSentinelPool(masterName, sentinelsSet, jedisConfig,30000);
    }
}

三、JedisHelper类

    public <T> List<T> listRange(String listName, Class<T> elementClazz, long start, long end) throws IOException {
        Assert.notNull(listName);
        Assert.notNull(elementClazz);
        Jedis jedis = null;
        boolean borrowOrOprSuccess = true;
        List<T> objects = new ArrayList<>();
        jedis=getJedis();
        try {
                   //同步锁解决高并发情况下的address in use异常
                   synchronized (this) {
                       if(jedis!=null){
                            List<String> elements = jedis.lrange(listName, start, end);                   
                            for (String element : elements) {
                                objects.add(objectMapper.readValue(element, elementClazz));
                            }
                       }
                   }            
        } catch (Exception e) {
            borrowOrOprSuccess = false;
            if (jedis != null)
                jedisPool.returnBrokenResource(jedis);
 
        } finally {
            if (borrowOrOprSuccess){
                jedisPool.returnResource(jedis);
            }            
        }
        return objects;
    }
    
    public  Jedis getJedis()  
    {  
            int timeoutCount = 0;  
            while (true) {  //如果第一次取不到,尝试取三次链接
                try  {  
                    Jedis jedis = jedisPool.getResource();  
                    return jedis;  
                } catch (Exception e)  { 
                    timeoutCount++;
                    if (timeoutCount > 3)  
                    {  
                         break;  
                    } 
                }  
            }  
            return null;  
    } 

 

posted on 2016-11-09 20:01  波神  阅读(1856)  评论(0编辑  收藏  举报