最近换了项目中,突然碰到redis了,对他的理解很有限,这里做个分享。
1.Redis的连接池(JedisPool)
说到连接池,我的第一反应是这可能跟数据源的C3P0类似。结果一查,恩,差不多。
Redis是一种C/S的模式,但是频繁的链接会导致花费在底层链接上的时间大大增加(因为Redis是基于内存的,读取效率高,假设一次数据交互总共用时30ms,超高性能的Redis数据库处理数据所花的时间可能不到1ms,也即是说前期的连接占用了29ms)。显然很不合理,怎么办呢。于是JedisPool就开始出现了。
连接池可以使在客户端建立多个连接并且不释放,想链接即可通过某算法建立连接,用完了,归还即可。这就免去了数据库链接所需要的时间。
但是如果超过连接池的上限以后,会怎么样呢:采用IO的多路复用来解决。
2.Redis的连接池的配置
package com.jedis;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Reids的工具类
* @author EdwardShen
*
* 2018年4月30日
*/
public class JedisUtil {
protected static ReentrantLock lockPool = new ReentrantLock();
protected static ReentrantLock lockJedis = new ReentrantLock();
protected static Logger logger = Logger.getLogger(JedisUtil.class);
//Redis服务器IP
private static String ADDR_ARRAY = "127.0.0.1,127.0.0.2";
//Redis的端口号
private static int PORT = 6379;
//访问密码
private static String AUTH = "http://blog.csdn.net/sx1119183530";
//可用连接实例的最大数目,默认值为8;
//如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
private static int MAX_ACTIVE = 8;
//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
private static int MAX_IDLE = 8;
//等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
private static int MAX_WAIT = 3000;
//超时时间
private static int TIMEOUT = 10000;
//在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
private static boolean TEST_ON_BORROW = false;
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连接池
*/
@Test
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);
System.out.println(ADDR_ARRAY.split(",")[0]+":"+ADDR_ARRAY.split(",")[1]);
jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[0], PORT, TIMEOUT, AUTH);
} 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, AUTH);
} catch (Exception e2) {
logger.error("Second create JedisPool error : " + e2);
}
}
}
/**
* 在多线程环境同步初始化
*/
private static void poolInit() {
lockPool.lock();
try {
if (jedisPool == null) {
initialPool();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lockPool.unlock();
}
}
public static Jedis getJedis() {
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 = StringUtils.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 = StringUtils.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);
}
}
测试类:
package com.jedis;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Test;
/**
* 测试类
* @author EdwardShen
*
* 2018年4月30日
*/
public class TestJedis extends Thread {
int i = 0;
public TestJedis(int i) {
this.i = i;
}
public void run() {
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date);
JedisUtil.setString("foo", time);
String foo = JedisUtil.getString("foo");
System.out.println("【输出>>>>】foo:" + foo + " 第:" + i + "个线程" + "当前时间:" + format.format(new Date()));
}
@Test
public void test()
{
System.out.println("kaishil !");
for (int i = 0; i < 10000; i++) {
TestJedis t = new TestJedis(i);
t.start();
}
}
}
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容