直接使用 new Jedis(host, port) 頻繁遇到連線超時。根因在於無連線池管理、無超時控制、異常時資源未正確歸還。本文詳細解析 JedisPool 正確使用姿勢、核心參數調優、異常處理模式與生產環境配置建議。
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100); // 最大連線數
config.setMaxIdle(20); // 最大閒置連線
config.setMaxWaitMillis(1000); // 獲取連線最大等待時間(ms)
JedisPool pool = new JedisPool(config, "192.168.1.100", 6379);
Jedis jedis = null;
boolean success = true;
try {
jedis = pool.getResource(); // 從池獲取連線
jedis.set("key", "value"); // 業務操作
} catch (JedisConnectionException e) {
success = false;
if (jedis != null) pool.returnBrokenResource(jedis); // 連線損壞歸還
} finally {
if (success && jedis != null) pool.returnResource(jedis); // 正常歸還
}
getResource() 失敗 vs 操作失敗,透過 jedis == null 判斷returnBrokenResource(),避免髒連線回池污染後續使用returnResource(),異常結束用 returnBrokenResource()| 參數 | 預設值 | 說明 | 調優建議 |
|---|---|---|---|
| maxTotal | 8 | 池中最大連線數(含閒置+使用中) | 業務峰值 QPS × 平均耗時(秒) × 1.5,上限受 Redis maxclients 限制 |
| maxIdle | 8 | 池中最大閒置連線數 | 設為 maxTotal 同值或略小,避免頻繁建立/銷毀 |
| minIdle | 0 | 池中最小閒置連線數 | 預熱用,設為預期基礎負載連線數 |
| maxWaitMillis | -1(無限) | 獲取連線最大等待時間,超時拋出 JedisConnectionException | 建議 1000-3000ms,防止業務線程無限阻塞 |
| testOnBorrow | false | 借用時驗證連線有效性 (PING) | 生產環境建議 true,代價極低 |
| testOnReturn | false | 歸還時驗證連線有效性 | 通常 false,借用時驗證即可 |
| testWhileIdle | true | 閒置驗證執行緒啟用 | 保持 true,配合 evictor 清理失效連線 |
| timeBetweenEvictionRunsMillis | 30000 | 閒置驗證執行緒掃描間隔 | 30-60 秒,平衡資源消耗與清理及時性 |
| minEvictableIdleTimeMillis | 60000 | 連線閒置超過此時間可被驅逐 | 60-300 秒,視網路穩定度調整 |
| numTestsPerEvictionRun | -1(全部) | 每次掃描檢查的連線數 | 大池設具體值(如 10)避免長時間佔用 |
| blockWhenExhausted | true | 連線耗盡時阻塞等待 vs 拋出異常 | 保持 true,配合 maxWaitMillis |
| lifo | true | LIFO(後進先出) vs FIFO | true 利於熱連線複用,減少閒置 |
# Maven# 內部依賴 commons-pool2 (非 1.x) redis.clients jedis 5.1.0 org.apache.commons commons-pool2 2.12.0
注意:Jedis 3.x+ 依賴 commons-pool2,非舊版 commons-pool-1.5.6.jar。
@Bean
public JedisPool jedisPool(@Value("${redis.host}") String host,
@Value("${redis.port}") int port,
@Value("${redis.password}") String password,
@Value("${redis.database:0}") int database) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(200);
config.setMaxIdle(50);
config.setMinIdle(10);
config.setMaxWaitMillis(2000);
config.setTestOnBorrow(true);
config.setTestOnReturn(false);
config.setTestWhileIdle(true);
config.setTimeBetweenEvictionRunsMillis(30000);
config.setMinEvictableIdleTimeMillis(60000);
config.setNumTestsPerEvictionRun(20);
config.setBlockWhenExhausted(true);
config.setLifo(true);
// Jedis 4.x+ 使用 Builder 模式
return new JedisPool(config, host, port, 2000, password, database);
}
maxWaitMillis=-1 導致業務線程無限掛起。解決:必須設定合理超時returnResource(),髒連線回池。解決:異常分支用 returnBrokenResource()new JedisPool()。解決:JedisPool 線程安全,應用生命週期單例Jedis 為同步阻塞客戶端,高併發下易成瓶頸。推薦遷移至 Lettuce(Netty 非阻塞、線程安全、支援 Reactor/Redis Cluster/Sentinel)。
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
LettucePoolingClientConfiguration config = LettucePoolingClientConfiguration.builder()
.poolConfig(GenericObjectPoolConfig<>()...)
.build();
return new LettuceConnectionFactory(new RedisStandaloneConfiguration(host, port), config);
}
JedisPool 是解決連線超時、資源管理的關鍵。核心在於:合理配置池參數、嚴格區分正常/異常歸還、啟用借用驗證與閒置清理。生產環境建議配合監控(連線使用率、等待時間、錯誤率)動態調優。高併發場景建議遷移至 Lettuce 非阻塞客戶端獲得更好擴展性。