发表于: 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



返回列表 返回列表
评论

    分享到