1. Jedis是什么?
官网
Jedis 是官方推荐的java客户端!SpringBoot的RedisTemplate的底层也是Jedis;
2. 为什么使用池化?
-  背景: - Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。
- Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。
 
-  解决方法: - 客户端角度:为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized;
- 服务器角度:利用setnx实现锁;
 
-  选择池化的好处: - 一个对象在其生命周期大致可分为 “创建”, “使用”, “销毁” 三大阶段, 那么它的总时间就是T1(创建)+T2(使用)+T3(销毁), 如果创建N个对象都需要这样的步骤的话是非常耗性能的,就算JVM对垃圾回收机制有优化,但"创建"和"销毁"多少总会占用部分资源;
 
-  使用池化的好处: - 减少 T1(创建)+T3(销毁) 所消耗的资源;
 
3. 如何使用池化?
JedisPool是redis 客户端jedis 的连接池,内部池对象的管理就是采用commons -pool2。采用它的有很多优点是,例如:避免过多的创建连对象、自动处理最大空闲数量,避免自己处理线程问题等等;
3.1 commons-pool2 是什么?
commons-pool2是Apache下一个开源的公共资源池;commons-pool官网 commons-pool 相关Api
3.2 commons-pool2 怎么使用?
-  核心组件: -  PooledObject(池对象) 
 用于封装对象(如:线程、数据库连接、TCP连接),将其包裹成可被池管理的对象。提供了两个默认的池对象实现:
-  DefaultPoolObject:用于非软引用的普通对象。 
-  PooledSoftReference:用于软引用的对象。 
 
-  
-  PooledObjectFactory(池对象工厂) 
 定义了操作PooledObject实例生命周期的一些方法,PooledObjectFactory必须实现线程安全。已经有两个抽象工厂:- BasePooledObjectFactory。
- BaseKeyedPooledObjectFactory。
 
-  Object Pool (对象池) 
 Object Pool负责管理PooledObject,如:借出对象,返回对象,校验对象,有多少激活对象,有多少空闲对象。有三个默认的实现类:- GenericObjectPool。
- ProsiedObjectPool。
- SoftReferenceObjectPool
- BorrowObject (借出对象)
- ReturnObject (返还对象)
 
3.3 demo
- 创建实例对象
package wang.pool;
 
/**
 * 测试
 *
 * @author wql
 * @date 2022/12/6 13:28
 */
public class TestWang {
     
    public TestWang(){}
     
    public void study(){
        System.out.println(" day day up !");
    }
}
- 创建工厂
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
 
/**
 * 测试对象 工厂
 *
 * @author wql
 * @date 2022/12/6 13:32
 */
public class TestWangFactory implements PooledObjectFactory<TestWang> {
 
    /**
     * 生产
     * <p>
     * 这个方法用于产生新的对象
     */
    @Override
    public PooledObject<TestWang> makeObject() throws Exception {
        return new DefaultPooledObject<TestWang>(new TestWang());
    }
 
    /**
     * 销毁
     * <p>
     * 这个方法用于销毁被validateObject判定为已失效的对象
     */
    @Override
    public void destroyObject(PooledObject<TestWang> pooledObject) throws Exception {
 
    }
 
    /**
     * 校验
     * <p>
     * 这个方法用于校验一个具体的对象是否仍然有效,已失效的对象会被自动交给destroyObject方法销毁。
     */
    @Override
    public boolean validateObject(PooledObject<TestWang> pooledObject) {
        return false;
    }
 
    /**
     * 激活
     * <p>
     * 设置为适合开始使用的状态
     */
    @Override
    public void activateObject(PooledObject<TestWang> pooledObject) throws Exception {
 
    }
 
    /**
     * 挂起
     * <p>
     * 这个方法用于将对象“挂起”——设置为适合开始休眠的状态
     */
    @Override
    public void passivateObject(PooledObject<TestWang> pooledObject) throws Exception {
 
    }
}
- 创建池
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
 
/**
 * 测试对象 池
 *
 * @author wql
 * @date 2022/12/6 13:36
 */
public class TestWangPool {
    private GenericObjectPool<TestWang> pool;
 
 
    public TestWangPool() {
        pool = new GenericObjectPool<TestWang>(new TestWangFactory(), new GenericObjectPoolConfig<TestWang>());
    }
 
    public TestWang getTestWang() {
        try {
            return pool.borrowObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
 
 
    public void returnTestWang(TestWang testWang) {
        pool.returnObject(testWang);
 
    }
 
}
- 测试
package wang.pool;
 
/**
 * @author wql
 * @date 2022/12/6 9:42
 */
public class TestMain {
    public static void main(String[] args) {
        TestWangPool testWangPool = new TestWangPool();
        TestWang testWang = testWangPool.getTestWang();
        testWang.study();
        testWangPool.returnTestWang(testWang);
    }
}
3.4 Jedis是如何使用common-pool2 实践的?

 

 
3.5 JedisPool参数说明

3.5.1 BaseObjectPoolConfig:封装公共的配置的参数
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
 
package org.apache.commons.pool2.impl;
 
import org.apache.commons.pool2.BaseObject;
 
public abstract class BaseObjectPoolConfig<T> extends BaseObject implements Cloneable {
    public static final boolean DEFAULT_LIFO = true;
    public static final boolean DEFAULT_FAIRNESS = false;
    public static final long DEFAULT_MAX_WAIT_MILLIS = -1L;
    public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1800000L;
    public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1L;
    public static final long DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS = 10000L;
    public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
    public static final boolean DEFAULT_TEST_ON_CREATE = false;
    public static final boolean DEFAULT_TEST_ON_BORROW = false;
    public static final boolean DEFAULT_TEST_ON_RETURN = false;
    public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
    public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
    public static final boolean DEFAULT_BLOCK_WHEN_EXHAUSTED = true;
    public static final boolean DEFAULT_JMX_ENABLE = true;
    public static final String DEFAULT_JMX_NAME_PREFIX = "pool";
    public static final String DEFAULT_JMX_NAME_BASE = null;
    public static final String DEFAULT_EVICTION_POLICY_CLASS_NAME = DefaultEvictionPolicy.class.getName();
    private boolean lifo = true;
    private boolean fairness = false;
    private long maxWaitMillis = -1L;
    private long minEvictableIdleTimeMillis = 1800000L;
    private long evictorShutdownTimeoutMillis = 10000L;
    private long softMinEvictableIdleTimeMillis = -1L;
    private int numTestsPerEvictionRun = 3;
    private EvictionPolicy<T> evictionPolicy = null;
    private String evictionPolicyClassName;
    private boolean testOnCreate;
    private boolean testOnBorrow;
    private boolean testOnReturn;
    private boolean testWhileIdle;
    private long timeBetweenEvictionRunsMillis;
    private boolean blockWhenExhausted;
    private boolean jmxEnabled;
    private String jmxNamePrefix;
    private String jmxNameBase;
 
    public BaseObjectPoolConfig() {
        this.evictionPolicyClassName = DEFAULT_EVICTION_POLICY_CLASS_NAME;
        this.testOnCreate = false;
        this.testOnBorrow = false;
        this.testOnReturn = false;
        this.testWhileIdle = false;
        this.timeBetweenEvictionRunsMillis = -1L;
        this.blockWhenExhausted = true;
        this.jmxEnabled = true;
        this.jmxNamePrefix = "pool";
        this.jmxNameBase = DEFAULT_JMX_NAME_BASE;
    }
 
   ....
}
3.5.2 GenericObjectPoolConfig:
继承BaseGenericObjectPool,封装了GenericObjectPool的配置。 此类不是线程安全的;它仅用于提供创建池时使用的属性。在创建单例的JedisPool 使用
public class GenericObjectPoolConfig<T> extends BaseObjectPoolConfig<T> {
    public static final int DEFAULT_MAX_TOTAL = 8;
    public static final int DEFAULT_MAX_IDLE = 8;
    public static final int DEFAULT_MIN_IDLE = 0;
    private int maxTotal = 8;
    private int maxIdle = 8;
    private int minIdle = 0;
}
3.5.3 JedisPoolConfig:
它继承了GenericObjectPoolConfig在空闲检测上的一些设置
public class JedisPoolConfig extends GenericObjectPoolConfig {
    public JedisPoolConfig() {
        this.setTestWhileIdle(true);
        this.setMinEvictableIdleTimeMillis(60000L);
        this.setTimeBetweenEvictionRunsMillis(30000L);
        this.setNumTestsPerEvictionRun(-1);
    }
}
4. JedisPool 参数说明( 摘自 阿里云 JedisPool资源池优化)
Jedis连接就是连接池中JedisPool管理的资源,JedisPool保证资源在一个可控范围内,并且保障线程安全。使用合理的GenericObjectPoolConfig配置能够提升Redis的服务性能,降低资源开销。详情可以点击链接查看
推荐配置:
 



















