目錄
Jedis提供了連接池JedisPool。由於Jedis對象不是線程安全的,所以一般會從連接池中取出一個Jedis對象獨佔,使用完畢後再歸還給連接池。
maven依賴:
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
</dependency>
1、JedisPool的應用
1.1 基本應用
資源池簡單應用代碼示例:
// 獲取連接池
JedisPool pool = new JedisPool();
// 從資源池中拿出可以鏈接對象
// 用try-with-resource自動調用close方法歸還資源
try(Jedis jedis = pool.getResource();) {
// 應用程序執行操作
}
1.2 封裝應用
上述寫法,如果使用者沒有使用try-with-resource並且忘記了歸還資源,可以對JedisPool做一層封裝,將歸還資源的操作封裝起來。
1、資源池:
public class RedisPool {
private JedisPool pool;
public RedisPool() {
this.pool = new JedisPool();
}
/**
* 執行任務
*
* @param callable
*/
public void execute(RedisCallable callable) {
try(Jedis jedis = pool.getResource()) {
callable.call(jedis);
}
}
}
2、回調接口:
public interface RedisCallable {
/**
* 回調方法,執行需要執行的任務
*
* @param jedis jedis
*/
void call(Jedis jedis);
}
3、使用:
public class RedisMain {
public static void main(String[] args) {
RedisPool pool = new RedisPool();
pool.execute((jedis) -> {
System.out.println(jedis.get("key"));
});
}
}
1.3 增加超時重試
網絡抖動情況下,需要增加超時重試機制,在捕獲到JedisConnectionException時可以進行重試。
可以按如下方式改造資源池:
public class RedisPool {
/**
* 最大重試次數
*/
private static final int MAX_RETRY = 3;
private JedisPool pool;
public RedisPool() {
this.pool = new JedisPool();
}
/**
* 執行任務
*
* @param callable
*/
public void execute(RedisCallable callable) {
int count = 0;
try (Jedis jedis = pool.getResource()) {
execute(callable, jedis, count);
}
}
private void execute(RedisCallable callable, Jedis jedis, int count) {
try {
callable.call(jedis);
} catch (JedisConnectionException e) {
if (count < MAX_RETRY) {
execute(callable, jedis, ++count);
} else {
throw e;
}
}
}
}
2、JedisPool配置
JedisPool入參最多的構造器:
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) {
super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password,
database, clientName));
}
上述參數可以分成兩部分:資源池配置,以及工廠配置。
2.1 工廠配置
JedisFactory的主要功能爲管理(創建,關閉,驗證)redis的連接客戶端jedis。從連接池獲取jedis連接資源,實際上看是從JedisPool的父類pool中獲取,而pool又委託給JedisFactory,最後由JedisFactory創建redis連接客戶端jedis。
- host:目標服務實例的域名或ip
- port:目標服務器的端口(Redis默認端口號是6379)
- connectionTimeout:連接超時時間
- soTimeout:socket超時時間
- password:密碼
- database:數據庫
- clientName:生產的客戶端實例名稱
2.2 資源池配置
資源池JedisPool使用GenericObjectPool的實例來傳入配置,而GenericObjectPool是BaseGenericObjectPool的子類。
核心參數:
- maxTotal:最大連接數;
- maxIdle:最大空閒連接數;
- minIdle:最小空閒連接數;
- blockWhenExhausted:表示當pool中的jedis實例都被分配完時,是否要進行阻塞;
- maxWaitMillis:當blockWhenExhausted爲true時,最大的阻塞時長。
空閒連接資源檢測相關:
- testOnCreate:在創建Jedis實例時,測試連接可用性,默認關閉,如果打開,則保證創建的都是連接可用的Jedis實例;
- testOnBorrow:在資源池借出Jedis實例時,測試連接可用性,默認關閉,如果打開,則保證借出的都是可用的;
- testOnReturn:在Jedis歸還Jedis資源池時,測試連接可用性,默認關閉;
- testWhileIdle:表示有一個idle object evitor線程對空閒的Jedis實例進行掃描,如果驗證失敗,此Jedis實例會被從資源池中刪除掉;這一項只有在timeBetweenEvictionRunsMillis大於0時纔有意義。
空閒連接資源驅逐相關:
- timeBetweenEvictionRunsMillis:表示idle object evitor兩次掃描之間要sleep的毫秒數;
- numTestsPerEvictionRun:表示idle object evitor每次掃描的最多的對象數;
- minEvictableIdleTimeMillis:空閒驅逐時間,表示一個對象至少停留在idle狀態的最短時間,然後才能被idle object evitor掃描並驅逐;這一項只有在timeBetweenEvictionRunsMillis大於0時纔有意義;
- softMinEvictableIdleTimeMillis:軟空閒驅逐時間,在minEvictableIdleTimeMillis基礎上,還需要檢測至少minIdle個對象已經在資源池裏,纔會進行驅逐;
- lifo:當借出的資源時,是使用LIFO(last in first out)策略,借出最新使用的資源;還是使用FIFO策略,借出最久沒有使用的資源。默認爲true,即LIFO;
- evictionPolicy:驅逐策略,接口,默認實現邏輯:資源的空閒毫秒數,如果大於空閒驅逐時間minEvictableIdleTimeMillis,或大於softMinEvictableIdleTimeMillis且當前的空閒資源數量大於配置的最小空閒資源數量,則進行驅逐
BaseGenericObjectPool的配置如下:
private volatile int maxTotal =
GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
private volatile boolean blockWhenExhausted =
BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
private volatile long maxWaitMillis =
BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS;
private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
private final boolean fairness;
private volatile boolean testOnCreate =
BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE;
private volatile boolean testOnBorrow =
BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW;
private volatile boolean testOnReturn =
BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN;
private volatile boolean testWhileIdle =
BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE;
private volatile long timeBetweenEvictionRunsMillis =
BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
private volatile int numTestsPerEvictionRun =
BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
private volatile long minEvictableIdleTimeMillis =
BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private volatile long softMinEvictableIdleTimeMillis =
BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private volatile EvictionPolicy<T> evictionPolicy;
private volatile long evictorShutdownTimeoutMillis =
BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS;
GenericObjectPool的配置如下:
/**
* The default value for the {@code maxTotal} configuration attribute.
* @see GenericObjectPool#getMaxTotal()
*/
public static final int DEFAULT_MAX_TOTAL = 8;
/**
* The default value for the {@code maxIdle} configuration attribute.
* @see GenericObjectPool#getMaxIdle()
*/
public static final int DEFAULT_MAX_IDLE = 8;
/**
* The default value for the {@code minIdle} configuration attribute.
* @see GenericObjectPool#getMinIdle()
*/
public static final int DEFAULT_MIN_IDLE = 0;
private int maxTotal = DEFAULT_MAX_TOTAL;
private int maxIdle = DEFAULT_MAX_IDLE;
private int minIdle = DEFAULT_MIN_IDLE;