发表于: 2017-09-21 16:24:39
1 650
今天完成的事情:
来研究一下redis的工具类,序列化这么简单的东西就不管了(逃
public class RedisUtil {
//Redis服务器IP
private static String ADDR = "127.0.0.1";
//Redis端口号
private static int PORT = 6379;
//"admin";//访问密码
private static String AUTH = null;
//可用连接实例的最大数目,默认值为8;
//如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
private static int MAX_ACTIVE = 1024;
//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
private static int MAX_IDLE = 200;
//等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
private static int MAX_WAIT = 10000;
private static int TIMEOUT = 10000;
//在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
private static boolean TEST_ON_BORROW = true;
private static JedisPool jedisPool = null;
/**
* 初始化Redis连接池
*/
static {
try {
JedisPoolConfig config = new JedisPoolConfig();
//config.setMaxActive(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMaxWaitMillis(MAX_WAIT);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取Jedis实例
* @return
*/
public synchronized static Jedis getJedis(){
try{
if(jedisPool != null){
Jedis resource =jedisPool.getResource();
return resource;
}else {
return null;
}
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* 释放Jedis资源
* @param jedis
*/
public static void close(final Jedis jedis){
if(jedis != null){
jedis.close();
}
}
}
先说明一下为什么使用工具类而不是简单的new一个jedis对象
正常情况下在new一个jedis对象之后,jedis会打开一条socket通道来和redis服务进行连接。所以在使用完之后我们需要把连接关掉,否则会占用系统资源。同时如果非常的频繁的创建和关闭jedis对象对系统性能也会有很大影响,因为构建socket是很耗时的,这时候就可以使用连接池来代替这种方法。
jedis的连接池需要一个依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
在构建连接池对象的时候,需要提供一些配置对象,及JedisPoolConfig。我们可以通过这个配置对象对连接池进行相关参数的配置
static {
try {
JedisPoolConfig config = new JedisPoolConfig();
//config.setMaxActive(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMaxWaitMillis(MAX_WAIT);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
} catch (Exception e) {
e.printStackTrace();
}
}
从连接池中获取jedis连接,同时会对dataSource进行设置
public synchronized static Jedis getJedis(){
try{
if(jedisPool != null){
Jedis resource =jedisPool.getResource();
return resource;
}else {
return null;
}
}catch (Exception e){
e.printStackTrace();
return null;
}
}
使用Jedis连接池之后,在每次用完连接对象后一定要记得把连接归还给连接池。Jedis对close方法进行了改造,如果是连接池中的连接对象,调用Close方法将会是把连接对象返回到对象池,若不是则关闭连接。
看一下close源码
public void close() {
if (this.dataSource != null) {
if (this.client.isBroken()) {
this.dataSource.returnBrokenResource(this);
} else {
this.dataSource.returnResource(this);
}
} else {
this.client.close();
}
}
可以看到,如果是从JedisPool取得的Jedis实例(Jedis的dataSource成员不为空,即指向 一个JedisPool),会进行相应的归还给JedisPool的操作,如果是单独生成的一个Jedis实例(Jedis的dataSource成员为空),则会直接断开与Redis服务器的连接。(迷)
测试一下吧
@Test
public void test(){
Jedis jedis =new Jedis("127.0.0.1",6379);
jedis.set("google输入法","真尼玛好用");
System.out.println(jedis.get("google输入法"));
jedis.close();
System.out.println(jedis.isConnected());
System.out.println(jedis.get("google输入法"));
System.out.println(jedis.isConnected());
}
这是没用连接池的结果,jedis.close直接断开和redis的连接了,但是再次连接jedis的时候它还是能连接上的,有点迷,看来是get方法能直接连上。
然后试一下连接池
@Test
public void test2(){
Jedis jedis = RedisUtil.getJedis();
jedis.set("google输入法","真尼玛好用");
System.out.println(jedis.get("google输入法"));
jedis.close();
System.out.println(jedis.isConnected());
System.out.println(jedis.get("google输入法"));
System.out.println(jedis.isConnected());
}
这里close的大意是将jedis实例归还给jedisPool,但并没有断开连接,嗯。。。
当然如果我就想断开连接就简单了
@Test
public void test2(){
Jedis jedis = RedisUtil.getJedis();
jedis.set("google输入法","真尼玛好用");
System.out.println(jedis.get("google输入法"));
jedis.quit();
System.out.println(jedis.get("google输入法"));
}
但是用jedis.isConnected还是能连接上的,迷。。
quit这个命令就是断开客户端连接的,还有一个更神奇的
jedis.disConnect,也是断开连接
这三个肯定是有区别的,但是我也看不懂源码也百度也找不到,先放着吧_(:з」∠)_
100年后。。。
研究了半天可以把工具类改成这样
public static void closeJedisPool(Jedis jedis) {
jedis.close();
if (jedis.isConnected()) {
try {
System.out.println("退出" + jedis.toString() + ":" + jedis.quit());
jedis.disconnect();
} catch (Exception e) {
System.out.println("退出失败");
e.printStackTrace();
}
}
System.out.println("退出"+jedis.toString());
}
首先get方法的时候是会建立连接的
protected Connection sendCommand(Command cmd, byte[]... args) {
try {
this.connect();
Protocol.sendCommand(this.outputStream, cmd, args);
++this.pipelinedCommands;
return this;
} catch (JedisConnectionException var6) {
JedisConnectionException ex = var6;
然后close方法在DataSource不是null的情况下并不会断开连接,必须之后再用一个quit手动断开,再加上一个disconnect可以再用get方法连接(这个disconnect真搜不到)
为什么源码没有注释呢,这一般人谁看得懂啊
明天计划的事情:
小课堂,争取做完任务6
评论