解决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; }