java端在使用jedispool 连接redis的时候,在高并发的时候经常卡死,或报连接异常,JedisConnectionException,或者getResource 异常等各种问题
在使用jedispool 的时候一定要注意两点
1。 在获取 jedisPool和jedis的时候加上线程同步,保证不要创建过多的jedispool 和 jedis
2。 用完Jedis实例后需要返还给JedisPool
整理了一下redis工具类,通过大量测试和高并发测试的
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Redis 工具类
*
@author
caspar
* https://blog.csdn.net/tuposky
*/
public
class
RedisUtil {
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
synchronized
void
poolInit() {
if (jedisPool ==
null) {
initialPool();
}
}
/**
* 同步获取Jedis实例
*
@return
Jedis
*/
public
synchronized
static
Jedis
getJedis() {
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);
}
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
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
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
static
String
getString(
String
key){
if(
getJedis() ==
null || !
getJedis().
exists(key)){
return
null;
}
return
getJedis().
get(key);
}
}
|
---|
其中 jedis官方现在最高版本为2.9.0 而jedis.close()取代pool.returnResource(Jedis)方法将3.0版本开始,所以暂时只能使用后者。
//官方重写了close。
try {
jedis =
pool.
getResource();
}
finally {
if (jedis !=
null) {
jedis.
close();
}
}