jedispool连redis高并发卡死的问题
程序员文章站
2022-05-28 14:17:15
java端在使用jedispool 连接redis的时候,在高并发的时候经常死锁,或报连接异常,jedisconnectionexception,或者getresource...
java端在使用jedispool 连接redis的时候,在高并发的时候经常死锁,或报连接异常,jedisconnectionexception,或者getresource 异常等各种问题
在使用jedispool 的时候一定要注意两点
1。 在获取 jedispool和jedis的时候加上线程同步,保证不要创建过多的jedispool 和 jedis
2。 用完jedis实例后需要返还给jedispool
整理了一下redis工具类,通过大量测试和高并发测试的
package com.caspar.util; import java.util.concurrent.locks.reentrantlock; import org.apache.log4j.logger; import redis.clients.jedis.jedis; import redis.clients.jedis.jedispool; import redis.clients.jedis.jedispoolconfig; /** * redis 工具类 * @author caspar * */ public class redisutil { protected static reentrantlock lockpool = new reentrantlock(); protected static reentrantlock lockjedis = new reentrantlock(); protected static logger logger = logger.getlogger(redisutil.class); //redis服务器ip private static string addr_array = fileutil.getpropertyvalue("/properties/redis.properties", "server"); //redis的端口号 private static int port = fileutil.getpropertyvalueint("/properties/redis.properties", "port"); //访问密码 // private static string auth = fileutil.getpropertyvalue("/properties/redis.properties", "auth"); //可用连接实例的最大数目,默认值为8; //如果赋值为-1,则表示不限制;如果pool已经分配了maxactive个jedis实例,则此时pool的状态为exhausted(耗尽)。 private static int max_active = fileutil.getpropertyvalueint("/properties/redis.properties", "max_active");; //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。 private static int max_idle = fileutil.getpropertyvalueint("/properties/redis.properties", "max_idle");; //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出jedisconnectionexception; private static int max_wait = fileutil.getpropertyvalueint("/properties/redis.properties", "max_wait");; //超时时间 private static int timeout = fileutil.getpropertyvalueint("/properties/redis.properties", "timeout");; //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的; private static boolean test_on_borrow = fileutil.getpropertyvalueboolean("/properties/redis.properties", "test_on_borrow");; private static jedispool jedispool = null; /** * redis过期时间,以秒为单位 */ public final static int exrp_hour = 60*60; //一小时 public final static int exrp_day = 60*60*24; //一天 public final static int exrp_month = 60*60*24*30; //一个月 /** * 初始化redis连接池 */ private static void initialpool(){ try { jedispoolconfig config = new jedispoolconfig(); config.setmaxtotal(max_active); config.setmaxidle(max_idle); config.setmaxwaitmillis(max_wait); config.settestonborrow(test_on_borrow); jedispool = new jedispool(config, addr_array.split(",")[0], port, timeout); } catch (exception e) { logger.error("first create jedispool error : "+e); try{ //如果第一个ip异常,则访问第二个ip jedispoolconfig config = new jedispoolconfig(); config.setmaxtotal(max_active); config.setmaxidle(max_idle); config.setmaxwaitmillis(max_wait); config.settestonborrow(test_on_borrow); jedispool = new jedispool(config, addr_array.split(",")[1], port, timeout); }catch(exception e2){ logger.error("second create jedispool error : "+e2); } } } /** * 在多线程环境同步初始化 */ private static void poolinit() { //断言 ,当前锁是否已经锁住,如果锁住了,就啥也不干,没锁的话就执行下面步骤 assert ! lockpool.isheldbycurrentthread(); lockpool.lock(); try { if (jedispool == null) { initialpool(); } }catch(exception e){ e.printstacktrace(); } finally { lockpool.unlock(); } } public static jedis getjedis() { //断言 ,当前锁是否已经锁住,如果锁住了,就啥也不干,没锁的话就执行下面步骤 assert ! lockjedis.isheldbycurrentthread(); lockjedis.lock(); if (jedispool == null) { poolinit(); } jedis jedis = null; try { if (jedispool != null) { jedis = jedispool.getresource(); } } catch (exception e) { logger.error("get jedis error : "+e); }finally{ returnresource(jedis); lockjedis.unlock(); } return jedis; } /** * 释放jedis资源 * @param jedis */ public static void returnresource(final jedis jedis) { if (jedis != null && jedispool !=null) { jedispool.returnresource(jedis); } } /** * 设置 string * @param key * @param value */ public synchronized static void setstring(string key ,string value){ try { value = stringutil.isempty(value) ? "" : value; getjedis().set(key,value); } catch (exception e) { logger.error("set key error : "+e); } } /** * 设置 过期时间 * @param key * @param seconds 以秒为单位 * @param value */ public synchronized static void setstring(string key ,int seconds,string value){ try { value = stringutil.isempty(value) ? "" : value; getjedis().setex(key, seconds, value); } catch (exception e) { logger.error("set keyex error : "+e); } } /** * 获取string值 * @param key * @return value */ public synchronized static string getstring(string key){ if(getjedis() == null || !getjedis().exists(key)){ return null; } return getjedis().get(key); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。