Jedis

作者: 一个理想主义的大兵 | 来源:发表于2019-05-22 23:58 被阅读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源码的粗略解读,主要想了解连接池的设计,以及通过线程安全的变量等机制,控制连接池的状态。

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

    相关文章

      网友评论

        本文标题:Jedis

        本文链接:https://www.haomeiwen.com/subject/cfkmzqtx.html