`
k1121
  • 浏览: 181056 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JedisPool使用原理及源代码

 
阅读更多

1,JedisPool的使用

<!-- 连接池的配置信息 -->
<bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig">
  <!-- 说明一个pool可以有多少个Jedis实例 -->
  <property name="maxActive" value="10" />
  <!-- 最大Idle-->
  <property name="maxIdle" value="5" />
  <!-- 最小Idle -->
  <property name="minIdle" value="1" />
  <!-- 获得一个jedis实例的时候是否检查连接可用性(ping()) -->
  <property name="testOnBorrow" value="true" />
  <!-- return 一个jedis实例给pool时,是否检查连接可用性(ping()) -->
  <property name="testOnReturn" value="true" />
  <!-- idle状态监测用异步线程evict进行检查, -->
  <property name="testWhileIdle" value="true" />
  <!-- 一次最多evict的pool里的jedis实例个数 -->
  <property name="numTestsPerEvictionRun" value="10" />
  <!-- test idle 线程的时间间隔 -->
  <property name="timeBetweenEvictionRunsMillis" value="60000" />
  <!--最大等待wait时间-->
  <property name="maxWait" value="3000" />
  <property name="whenExhaustedAction" value="" />
    //WHEN_EXHAUSTED_FAIL = 0; 直接抛出异常throw new NoSuchElementException("Pool exhausted");
    //WHEN_EXHAUSTED_BLOCK = 1;borrowObject()将会阻塞,直到有可用新的或者空闲的object为止,或者如果配置了maxWait,
                            //如果请求阻塞超时,将抛出NoSuchElementException.如果maxWait为负数,请求将会无限制的阻
                            //塞下去,默认配置。
    //WHEN_EXHAUSTED_GROW = 2;borrowObject()将会继续创建新的对象,并返回,因此,pool维护的对像数将超出maxActive;
                            //
</bean>
public String set(String key, String value) {
    Jedis jedis = null;
    boolean success = true;
    try {
        jedis = this.pool.getResource();
        return jedis.set(key, value);
    }catch (JedisException e) {
        success  = false;
        if(jedis != null){
            pool.returnBrokenResource(jedis);
        }
        throw e;
    }finally{
        if(success && jedis != null){
            this.pool.returnResource(jedis);
        }
    }
}

获取Jedis

pool.getResource();

这个可以直接看Pool的getResource方法,

最终还是GenericObjectPool的borrowObject()方法借用对象

@SuppressWarnings("unchecked")
public T getResource() {
    try {
        return (T) internalPool.borrowObject();
    } catch (Exception e) {
        throw new JedisConnectionException(
                "Could not get a resource from the pool", e);
    }
}

用完归还,调用的是GenericObjectPool的returnObject()方法

pool.returnResource(jedis)
//JedisPool.java
public void returnResource(final BinaryJedis resource) {
    returnResourceObject(resource);
}
//Pool.java
public void returnResourceObject(final Object resource) {
try {
    internalPool.returnObject(resource);
} catch (Exception e) {
    throw new JedisException(
            "Could not return the resource to the pool", e);
}
}

出错,调用的是GenericObjectPool的invalidateObject()方法

最后在JedisFactory的destroyObject()中调用jedis.quit()请求Server关闭连接

pool.returnBrokenResource(jedis)
//JedisPool.java
public void returnBrokenResource(final BinaryJedis resource) {
    returnBrokenResourceObject(resource);
}
//Pool.java
protected void returnBrokenResourceObject(final Object resource) {
    try {
        //失效
        internalPool.invalidateObject(resource);
    } catch (Exception e) {
        throw new JedisException(
                "Could not return the resource to the pool", e);
    }
}
//GenericObjectPool
public void invalidateObject(Object obj)
throws Exception
{
try
{
  if (this._factory != null)
    this._factory.destroyObject(obj);
}
finally {
  synchronized (this) {
    this._numActive -= 1;
    allocate();
  }
}
}
//JedisFactory
public void destroyObject(final Object obj) throws Exception {
    if (obj instanceof Jedis) {
        final Jedis jedis = (Jedis) obj;
        if (jedis.isConnected()) {
            try {
                try {
                    jedis.quit();
                } catch (Exception e) {
                }
                jedis.disconnect();
            } catch (Exception e) {

            }
        }
    }
}

JedisPool源代码

package redis.clients.jedis;

import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool.Config;

import redis.clients.util.Pool;

public class JedisPool extends Pool<Jedis> {

    public JedisPool(final Config poolConfig, final String host) {
        this(poolConfig, host, Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE);
    }

    public JedisPool(String host, int port) {
        this(new Config(), host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE);
    }

    public JedisPool(final String host) {
        this(host, Protocol.DEFAULT_PORT);
    }

    public JedisPool(final Config poolConfig, final String host, int port,
            int timeout, final String password) {
        this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE);
    }

    public JedisPool(final Config poolConfig, final String host, final int port) {
        this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE);
    }

    public JedisPool(final Config poolConfig, final String host, final int port, final int timeout) {
        this(poolConfig, host, port, timeout, null, Protocol.DEFAULT_DATABASE);
    }

    public JedisPool(final Config poolConfig, final String host, int port, int timeout, final String password,
                     final int database) {
        super(poolConfig, new JedisFactory(host, port, timeout, password, database));
    }


    public void returnBrokenResource(final BinaryJedis resource) {
        returnBrokenResourceObject(resource);
    }

    public void returnResource(final BinaryJedis resource) {
        returnResourceObject(resource);
    }

    /**
     * PoolableObjectFactory custom impl.
     */
    private static class JedisFactory extends BasePoolableObjectFactory {
        private final String host;
        private final int port;
        private final int timeout;
        private final String password;
        private final int database;

        public JedisFactory(final String host, final int port,
                final int timeout, final String password, final int database) {
            super();
            this.host = host;
            this.port = port;
            this.timeout = timeout;
            this.password = password;
            this.database = database;
        }

        public Object makeObject() throws Exception {
            final Jedis jedis = new Jedis(this.host, this.port, this.timeout);

            jedis.connect();
            if (null != this.password) {
                jedis.auth(this.password);
            }
            if( database != 0 ) {
                jedis.select(database);
            }

            return jedis;
        }

        public void destroyObject(final Object obj) throws Exception {
            if (obj instanceof Jedis) {
                final Jedis jedis = (Jedis) obj;
                if (jedis.isConnected()) {
                    try {
                        try {
                            jedis.quit();
                        } catch (Exception e) {
                        }
                        jedis.disconnect();
                    } catch (Exception e) {

                    }
                }
            }
        }

        public boolean validateObject(final Object obj) {
            if (obj instanceof Jedis) {
                final Jedis jedis = (Jedis) obj;
                try {
                    return jedis.isConnected();/* && jedis.ping().equals("PONG");*/
                } catch (final Exception e) {
                    return false;
                }
            } else {
                return false;
            }
        }
    }
}

其中JedisFactory继承自BasePoolableObjectFactory,只实现了3个方法

makeObject(),连接,new Socket()

destroyObject()--断开连接,

validateObject()--ping


Pool源代码

package redis.clients.util;

import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisException;

public abstract class Pool<T> {
    private final GenericObjectPool internalPool;

    public Pool(final GenericObjectPool.Config poolConfig,
            PoolableObjectFactory factory) {
        this.internalPool = new GenericObjectPool(factory, poolConfig);
    }

    @SuppressWarnings("unchecked")
    public T getResource() {
        try {
            return (T) internalPool.borrowObject();
        } catch (Exception e) {
            throw new JedisConnectionException(
                    "Could not get a resource from the pool", e);
        }
    }

    public void returnResourceObject(final Object resource) {
        try {
            internalPool.returnObject(resource);
        } catch (Exception e) {
            throw new JedisException(
                    "Could not return the resource to the pool", e);
        }
    }

    public void returnBrokenResource(final T resource) {
        returnBrokenResourceObject(resource);
    }

    public void returnResource(final T resource) {
        returnResourceObject(resource);
    }

    protected void returnBrokenResourceObject(final Object resource) {
        try {
            //失效
            internalPool.invalidateObject(resource);
        } catch (Exception e) {
            throw new JedisException(
                    "Could not return the resource to the pool", e);
        }
    }

    public void destroy() {
        try {
            internalPool.close();
        } catch (Exception e) {
            throw new JedisException("Could not destroy the pool", e);
        }
    }
}

JedisPoolConfig源代码

public class JedisPoolConfig extends Config {
    public JedisPoolConfig() {
        // defaults to make your life with connection pool easier :)
        setTestWhileIdle(true);
        setMinEvictableIdleTimeMillis(60000);
        setTimeBetweenEvictionRunsMillis(30000);
        setNumTestsPerEvictionRun(-1);
    }

    public int getMaxIdle() {
        return maxIdle;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public int getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public int getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(int maxActive) {
        this.maxActive = maxActive;
    }

    public long getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public byte getWhenExhaustedAction() {
        return whenExhaustedAction;
    }

    public void setWhenExhaustedAction(byte whenExhaustedAction) {
        this.whenExhaustedAction = whenExhaustedAction;
    }

    public boolean isTestOnBorrow() {
        return testOnBorrow;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public boolean isTestOnReturn() {
        return testOnReturn;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public boolean isTestWhileIdle() {
        return testWhileIdle;
    }

    public void setTestWhileIdle(boolean testWhileIdle) {
        this.testWhileIdle = testWhileIdle;
    }

    public long getTimeBetweenEvictionRunsMillis() {
        return timeBetweenEvictionRunsMillis;
    }

    public void setTimeBetweenEvictionRunsMillis(
            long timeBetweenEvictionRunsMillis) {
        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }

    public int getNumTestsPerEvictionRun() {
        return numTestsPerEvictionRun;
    }

    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
    }

    public long getMinEvictableIdleTimeMillis() {
        return minEvictableIdleTimeMillis;
    }

    public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    public long getSoftMinEvictableIdleTimeMillis() {
        return softMinEvictableIdleTimeMillis;
    }

    public void setSoftMinEvictableIdleTimeMillis(
            long softMinEvictableIdleTimeMillis) {
        this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
    }

}
分享到:
评论

相关推荐

    jedis源码 (学习jedis)

    这个压缩包文件"jedis-master"很可能包含了Jedis的完整源代码,包括测试用例,是学习Jedis的绝佳资源。 1. **Jedis基本使用**: Jedis的使用通常始于创建Jedis实例,通过连接池管理连接。在源码中,你可以看到`...

    jedis-3.0.0.jar(全)

    `jedis-3.0.0-sources.jar`则包含了Jedis的源代码,这对于开发者深入理解Jedis的工作原理、进行二次开发或者调试错误至关重要。通过阅读源码,开发者可以了解到Jedis如何封装网络通信,如何处理各种Redis命令,以及...

    Jedis2.1.0源码与Jar包

    `配置连接池参数,然后`JedisPool pool = new JedisPool(config, "localhost", 6379);`创建连接池,`Jedis jedis = pool.getResource();`获取连接,操作完成后使用`jedis.close();`归还连接。 ### Jedis与Redis其他...

    redis3.2+jedis2.8.jar+common-pool2.jar+common-pool2-source.rar

    Common-Pool2-source.rar则包含了Common-Pool2的源代码,开发者可以通过阅读源码来了解其内部工作原理,进行更深入的定制或优化。 在使用Redis3.2+jedis2.8.jar进行Java开发时,首先需要在项目中引入Jedis库,配置...

    jedis-jedis-2.8.0.tar.gz

    在这个压缩包"jedis-jedis-2.8.0.tar.gz"中,包含了Jedis库的源代码、文档和其他相关资源,使得开发者可以方便地在项目中集成和使用。 1. **Redis介绍**:Redis是一个开源的、基于键值对的数据存储系统,常被用作...

    jedis-2.9.0 最新版Redis客户端CSDN下载

    3. `jedis-2.9.0-sources.jar`:这个文件包含了Jedis的源代码,开发者可以查看源码来理解Jedis的工作原理,对于学习、调试和贡献代码非常有帮助。 Jedis的主要特性包括: - 连接管理:支持连接池,可配置连接超时...

    jedis-2.1.0-sources.jar

    在"jedis-2.1.0-sources.jar"中,包含了Jedis库的源代码,这对于我们深入理解其内部实现、调试或扩展功能非常有价值。通过查看源码,我们可以了解到以下关键知识点: 1. **连接管理**:Jedis提供了连接池...

    jedis-jedis-2.5.0.zip

    - `src/main/java`目录下的源代码,包含了所有Jedis的实现类和接口,开发者可以查看源码理解其工作原理。 - `src/test/java`目录包含测试代码,这些测试用例展示了如何使用Jedis进行各种操作,有助于快速上手。 - `...

    jedis 2.9.0 API、jar包、source

    3. **jedis-2.9.0-sources.jar**:这个源代码jar包包含了Jedis的完整源代码,对于开发者来说是一个宝贵的学习资源。通过阅读源码,可以深入了解Jedis如何实现与Redis的通信,理解内部工作原理,以及进行自定义扩展或...

    redis所需jar包

    3. jedis-2.1.0-sources.jar:这个文件包含了Jedis源代码,对于开发者来说非常有用,可以方便地查看和理解内部实现,进行自定义扩展或者调试。源码可以帮助我们深入学习Jedis的工作原理,比如它是如何执行命令、处理...

    jedis-jedis-1.4.0.tar.gz

    1. **源代码**:解压后,你可以看到Jedis的源码结构,这有助于理解其内部工作原理,如连接管理、命令执行逻辑、异常处理等。通过阅读源码,开发者可以自定义扩展或优化Jedis的功能,以满足特定需求。 2. **文档**:...

    jedis-3.1.0.jar 最新

    2. `jedis-3.1.0-sources.jar`:这个文件包含了Jedis库的源代码,对于开发者来说,它提供了查看和理解库内部工作原理的机会,有助于调试和学习。 3. `commons-pool2-2.4.3.jar`:这是一个Apache Commons Pool库的...

    redis resources

    "sources" 文件可能包含 Jedis 的源代码,对于深入理解其工作原理和定制开发非常有用。不过,由于提供的文件名称列表只有一个“新建文件夹”,具体的资源内容无法详细描述,但根据上述信息,你可以围绕 Redis 和 ...

    redis驱动包

    `jedis-2.1.0-sources.jar`则包含了源代码,对于开发者来说,查看源代码有助于理解和学习Jedis的工作原理,方便进行自定义扩展或调试。 2. **Apache Commons Pool**: `commons-pool.jar` 是Apache Commons项目中的...

Global site tag (gtag.js) - Google Analytics