首页 > 编程 > Java > 正文

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

2019-11-06 07:47:12
字体:
来源:转载
供稿:网友
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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表