您的位置:首页 > 数据库 > Redis

在Java中使用Jedis操作Redis,在高并发的情况下,应用卡死、报无法获取连接错误的处理方式

2017-03-04 11:29 555 查看
1.JedisUtil:工具类,单例,避免获取多个jedisPool 对象

package JedisTest;

import org.apache.commons.lang.StringUtils;

import redis.clients.jedis.Jedis;

import redis.clients.jedis.JedisPool;

import redis.clients.jedis.JedisPoolConfig;

/**

 * Jedis工具类

 * @author lanchunqiu

 *

 */

public class JedisUtil {

    private static int PORT = 6379;

    /**

     * 可用连接实例的最大数目,如果不设默认为8,;如果赋值为-1表示不限制;如果pool已经分配了MAX_ACTIVE个jedis实例,则此时pool的状态为exhausted(耗尽)

     */

    private static int MAX_ACTIVE = 500;

    

    /**

     * 控制一个pool最多有多少个状态为idle(空闲)的jedis实例,不设默认值为8

     */

    private static int MAX_IDLE = 10;

    

    /**

     * 控制一个pool最少有多少个状态为空闲的jedis实例

     */

    private static int MIN_IDLE = 100;

    

    /**

     * 在borrow一个jedis实例时,是否提前进行validate(验证)操作,如果为true,则得到的jedis实例都是可用的

     */

    private static boolean TEST_ON_BOOROW = true;

    

    /**

     * 在将连接放回池中前,自动检验连接是否有效  

     */

    private static boolean TEST_ON_RETURN = true;

    

    /**

     * 自动测试池中的空闲连接是否都是可用连接  

     */

    private static boolean TEST_WHILE_IDLE = true;

    /**

     * 等待一个可用连接的最大时间,单位毫秒,默认值为-1,表示用不超时;如果超过等待时间,则直接抛出JedisConnectionException

     */

    private static int MAX_WAIT = 60000;

    

    /**

     * 每次释放连接的最大数目

     */

    private static int NUM_TESTS_PER_EVICTION_RUN = 10;

    

    /**

     * 释放连接的扫描间隔(毫秒)

     */

    private static int TIME_BETWEEN_EVICTION_RUNS_MILLIS = 10;

    

    /**

     * 连接空闲多久后释放(毫秒), 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放

     */

    private static int SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS= 100;

    

    private static int TIMEOUT = 100000;

    

    private static JedisPool jedisPool = null; 

    private static JedisUtil jedisUtil = null;

    protected JedisUtil(){

    try{
System.out.println("初始化redis缓存!"); 
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxWaitMillis(MAX_WAIT);
config.setMaxTotal(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMinIdle(MIN_IDLE);
config.setTestOnBorrow(TEST_ON_BOOROW);
       config.setTestOnReturn(TEST_ON_RETURN);  
       config.setTestWhileIdle(TEST_WHILE_IDLE);  
       config.setNumTestsPerEvictionRun(NUM_TESTS_PER_EVICTION_RUN);
       config.setTimeBetweenEvictionRunsMillis(TIME_BETWEEN_EVICTION_RUNS_MILLIS);
       config.setMinEvictableIdleTimeMillis(SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);

jedisPool = new JedisPool(config, "127.0.0.1",PORT,TIMEOUT,"asopa_redis");
//jedisPool = new JedisPool(config, "127.0.0.1",PORT);

    }catch(Exception e){
System.out.println("初始化JedisPool异常:" + e);
jedisPool = null;
}

    }

    

    public static synchronized JedisUtil getInstance(){

    if(null == jedisUtil){

    jedisUtil = new JedisUtil();

    }

    return jedisUtil;

    }

    

    /**

     * 设置 String

     * @param key

     * @param value

     */

    public static void setString(String key ,String value){

    Jedis jedis = null;

        try {

        System.out.println("【存】可用连接数"+jedisPool.getNumActive());

        jedis = jedisPool.getResource();

            value = StringUtils.isEmpty(value) ? "" : value;

            jedis.set(key,value);

        } catch (Exception e) {

            System.out.println("Set key error : " + e);

        } finally{
jedisPool.returnResource(jedis);//注意:每次使用完jedis时一定要释放
}

    }

    

    /**

     * 取值

     * @param key

     * @return

     */

    public static String get(String key){

    Jedis jedis = null;

    try{

    System.out.println("【取】可用连接数"+jedisPool.getNumActive());

    jedis = jedisPool.getResource();

    return jedis.get(key);

    }

    catch(Exception e){

    System.out.println("从缓存中取值失败:"+e.getMessage());

    return null;

    } finally{

    jedisPool.returnResource(jedis);

    }

   

    }

}

2.JedisTestThread 线程类

package JedisTest;

/**

 * 

 * @author lanchunqiu

 *

 */

public class JedisTestThread extends Thread{
private JedisUtil jedisUtil = null;
public JedisTestThread(int i,JedisUtil jedisUtil){
System.out.println("=======线程"+i+"========"+jedisUtil.hashCode());
this.jedisUtil = jedisUtil;
}

public void run(){
jedisUtil.setString("foo1", "foo1");
System.out.println(jedisUtil.get("foo1"));
}

}

3.测试类:开启了1000个线程,如果想要启动更多的线程,就需要调整MAX_ACTIVE 参数值,开启1000个线程时,我设置的MAX_ACTIVE =500

package JedisTest;

import java.io.IOException;

/**

 * 

 * @author lanchunqiu

 *

 */

public class JedisTest {
public static void main(String[] args) throws IOException {
JedisUtil jedisUtil = JedisUtil.getInstance();
for (int i=0;i<1000;i++){
JedisTestThread thread1 = new JedisTestThread(i+1,jedisUtil);
thread1.start();
}
}

}

4.测试结果:就算连接数为0时也没出现异常,占用的连接会很快释放。

还请大牛多指教!

5.使用的jar包:

(1)jedis-2.8.0.jar

(2)commons-pool2-2.4.2.jar

(3)commons-lang-2.4.jar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  redis java jedis 并发