jedis源码分析(二)-JedisPool连接池实现

上一章节我们通过jedis学习了实现存放机制,本章节我们通过jedisPool的操作理解连接池的应用,jedisPool的源码实现。
jedisPool连接池示例
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolUtil {

    private volatile JedisPool pool;
    private Jedis jedis;
    private final String host;
    private final int port;
    private String password;

    public JedisPoolUtil(final String host, final int port) {
        this.host = host;
        this.port = port;
        initPool();
    }

    public JedisPoolUtil(final String host, final int port, final String password) {
        this.host = host;
        this.port = port;
        this.password = password;
        initPool();
    }

    public JedisPool initPool() {
        if (pool == null) {
            if (password != null) {
                JedisPoolConfig config = new JedisPoolConfig();
                config.setMaxIdle(100);
                config.setMaxWaitMillis(1000);
                // 设置空间连接
                config.setMaxIdle(10);
                pool = new JedisPool(config, host, port, 2000, password);
            } else {
                pool = new JedisPool(host, port);
            }
            System.out.println("连接池创建成功");
        }
        return pool;
    }

    public Jedis initJedis() {
        if(jedis==null) {
            jedis = pool.getResource();
        }
        System.out.println("jedis创建成功");
        return jedis;
    }

    public String set(String key, String value) {
        if (jedis == null) {
            jedis = initJedis();
        }
        String result = jedis.set(key, value);
        if ("OK".equals(result)) {
            jedis.close();
        }
        return result;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            JedisPoolUtil jedisPoolUtil = new JedisPoolUtil("127.0.0.1", 4100);
            System.out.println(jedisPoolUtil.set("test" + i, "value" + i));
        }
    }

}

使用jedisPool连接池,实例化jedisPool对象,jedisPool类提供了很多构造方法,可以根据自己的需要去选择构造方法,
 public JedisPool(String host, int port) {
    this(new GenericObjectPoolConfig(), host, port, Protocol.DEFAULT_TIMEOUT, null,
        Protocol.DEFAULT_DATABASE, null);
  }
 public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,
      final int connectionTimeout, final int soTimeout, final String password, final int database,
      final String clientName, final boolean ssl, final SSLSocketFactory sslSocketFactory,
      final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
    super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password,
        database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier));
  }
  public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, final int timeout,
      final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
      final HostnameVerifier hostnameVerifier) {
    this(poolConfig, uri, timeout, timeout, sslSocketFactory, sslParameters, hostnameVerifier);
  }
  public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri,
      final int connectionTimeout, final int soTimeout) {
    super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, null, false,
        null, null, null));
  }
  public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri,
      final int connectionTimeout, final int soTimeout, final SSLSocketFactory sslSocketFactory,
      final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
    super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, null,
        (uri.getScheme() !=null && uri.getScheme().equals("rediss")), sslSocketFactory,
        sslParameters, hostnameVerifier));
  }
这里实例化了一个实现了
org.apache.commons.pool2.PooledObjectFactory<Jedis>接口类的JedisFactory工厂类对象,该所有对象的创建销毁、激活和有效性验证都在JedisFactory工厂类中进行,
poolObjectFactory提供了五个接口方法:
public interface PooledObjectFactory<T> {
  PooledObject<T> makeObject() throws Exception;// 创建对象的方法
  void destroyObject(PooledObject<T> p) throws Exception;// 销毁对象的方法。
  boolean validateObject(PooledObject<T> p); //校验对象有消息的方法。
  void activateObject(PooledObject<T> p) throws Exception;// 激活对象的方法
  void passivateObject(PooledObject<T> p) throws Exception;// 钝化对象的方法。返回到空闲对象实例池
}

由于jedisPool继承了Pool<Jedis>,Pool实现了Closeable接口,最终委托了pool的实例化方法,调用了Pool类中的initPoll方法,在initPool方法中new了一个GenericObjectPool方法,该方法是org.apache.commons.pool2.impl.GenericObjectPool.GenericObjectPool中的连接池实现方法
public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
    initPool(poolConfig, factory);
  }

 public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
    if (this.internalPool != null) {
      try {
        closeInternalPool();
      } catch (Exception e) {
      }
    }
    this.internalPool = new GenericObjectPool<T>(factory, poolConfig);
  }
GenericObjectPool方法中有两个参数:一个GenericObjectPoolConfig配置项分装类,一个是 PooledObjectFactory工厂类
获取到连接池后从连接池中获取jedis连接对象
 @Override
  public Jedis getResource() {
    Jedis jedis = super.getResource();
    jedis.setDataSource(this);
    return jedis;
  }

 public T getResource() {
    try {
      return internalPool.borrowObject();
    } catch (NoSuchElementException nse) {
      throw new JedisException("Could not get a resource from the pool", nse);
    } catch (Exception e) {
      throw new JedisConnectionException("Could not get a resource from the pool", e);
    }
  }
对于jedis Pool只能进行单实例的链接操作,但是对于数据量大的时候,单实例不能满足需求. 这个时候就需要对实例进行“分片”。Jedis也是提供了分片的支持,后面也会总结一个jedis分片的实现.

阅读更多
文章标签: redis
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭