分布式缓存(Redis)

Jedis

2019-05-22  本文已影响0人  一个理想主义的大兵

Jedis是Redis的Java客户端,连接池使用commons-pool2。此文记录Jedis的设计,也探讨连接池的实现。

版本:jedis-3.1.0-m1

Jedis对象

Jedis对象的继承关系:Jedis—>BinaryJedis- - - ->BasicCommandsBinaryJedisCommands等,其中BinaryJedis组合了Client对象(Client—>BinaryClient—>ConnectionConnection对象组合了socket输入输出流等连接对象)

JedisPool初始化

JedisPool的构造方法很多(可以改造成Builder Pattern,更清晰),可以通过JedisConfig进行配置

    JedisPoolConfig config = new JedisPoolConfig();
    config.setMaxActive(MAX_ACTIVE);
    config.setMaxIdle(MAX_IDLE);
    config.setMaxWait(MAX_WAIT);
    config.setMaxWait(MAX_WAIT);
    config.setTestOnBorrow(TEST_ON_BORROW);
    jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);

JedisPool的继承关系:JedisPool —>JedisPoolAbstract—>Pool

JedisPool的构造,依赖于抽象父类Pool的构造函数,如下:

//Pool中内置的属性是commons-pool2的GenericObjectPool
    private final GenericObjectPool internalPool;

    public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
    initPool(poolConfig, factory);
  }

  public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
        //...
    this.internalPool = new GenericObjectPool<T>(factory, poolConfig);
  }

Pool中内置的属性是commons-pool2GenericObjectPool,即最终的连接池对象:

    public GenericObjectPool(final PooledObjectFactory<T> factory,
            final GenericObjectPoolConfig config) {
                //...
        this.factory = factory;
        idleObjects = new LinkedBlockingDeque<>(config.getFairness());
                //...
    }

其中构造参数final PooledObjectFactory<T> factory,是外层构造时传入的JedisFactory,其实现了接口PoolObjectFactory,并实现了makeObject()等相关方法,即产生Jedis类的真正工厂。

Jedis连接获取

上文提到的makeObject()真正被调用的时候,是在连接获取时,进行调用并创建Jedis对象 (当然是有条件的,即下文提到的存活队列中无可用对象,并未达到上限时)

        private PooledObject<T> create() throws Exception {
      //判断连接池容量的逻辑...
        final PooledObject<T> p;
        try {
            p = factory.makeObject();
        } catch (final Exception e) {
            createCount.decrementAndGet();
            throw e;
        }finally {
            synchronized (makeObjectCountLock) {
                makeObjectCount--;
                //此处唤醒所有等待连接的线程
                makeObjectCountLock.notifyAll();
            }
        }
    }

Jedis连接关闭

这里必须要提到,在连接池对象中(GenericObjectPool)的一个重要属性:

private final LinkedBlockingDeque<PooledObject<T>> idleObjects;

这个阻塞队列是维护存活Jedis对象的容器,当连接关闭时,Jedis对象归还连接池,即存入此队列,保持连接的存活。

        final int maxIdleSave = getMaxIdle();
        if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
                try {
                        destroy(p);
        } catch (final Exception e) {
            swallowException(e);
        }
        } else {        
                if (getLifo()) {
                        idleObjects.addFirst(p);
                } else {
                    idleObjects.addLast(p);
                }
    }

总结

此文只是对Jedis源码的粗略解读,主要想了解连接池的设计,以及通过线程安全的变量等机制,控制连接池的状态。

还有诸多细节,待后续补充。

上一篇下一篇

猜你喜欢

热点阅读