日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

JedisPool資源池優化

JedisPool是Jedis客戶端的連接池,合理地設置JedisPool資源池參數能夠有效地提升Redis性能與資源利用率。本文將對JedisPool的使用和資源池的參數進行詳細說明,并提供優化配置的建議。

使用方法

以Jedis 2.9.0為例,其Maven依賴如下:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
    <scope>compile</scope>
</dependency>

Jedis使用Apache Commons-pool2對資源池進行管理,在定義JedisPool時需注意其關鍵參數GenericObjectPoolConfig(資源池)。該參數的使用示例如下,其中的參數的說明請參見下文。

GenericObjectPoolConfig jedisPoolConfig = new GenericObjectPoolConfig();
jedisPoolConfig.setMaxTotal(...);
jedisPoolConfig.setMaxIdle(...);
jedisPoolConfig.setMinIdle(...);
jedisPoolConfig.setMaxWaitMillis(...);
...

JedisPool的初始化方法如下:

// redisHost為實例的IP, redisPort 為實例端口,redisPassword 為實例的密碼,timeout 既是連接超時又是讀寫超時。
JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort, timeout, redisPassword);
// 執行命令如下。
Jedis jedis = null;
try {
    jedis = jedisPool.getResource();
    // 具體的命令。
    jedis.executeCommand()
} catch (Exception e) {
    logger.error(e.getMessage(), e);
} finally {
    // 在JedisPool模式下,Jedis會被歸還給資源池。
    if (jedis != null) 
        jedis.close();
}

參數說明

Jedis連接就是連接池中JedisPool管理的資源,JedisPool保證資源在一個可控范圍內,并且保障線程安全。使用合理的GenericObjectPoolConfig配置能夠提升Redis的服務性能,降低資源開銷。下列兩表將對一些重要參數進行說明,并提供設置建議。

表 1. 資源設置與使用相關參數

參數

說明

默認值

建議

maxTotal

資源池中的最大連接數

8

參見關鍵參數設置建議

maxIdle

資源池允許的最大空閑連接數

8

參見關鍵參數設置建議

minIdle

資源池確保的最少空閑連接數

0

參見關鍵參數設置建議

blockWhenExhausted

當資源池用盡后,調用者是否要等待。只有當值為true時,下面的maxWaitMillis才會生效。

true

建議使用默認值。

maxWaitMillis

當資源池連接用盡后,調用者的最大等待時間(單位為毫秒)。

-1(表示永不超時)

不建議使用默認值。

testOnBorrow

向資源池借用連接時是否做連接有效性檢測(ping)。檢測到的無效連接將會被移除。

false

業務量很大時候建議設置為false,減少一次ping的開銷。

testOnReturn

向資源池歸還連接時是否做連接有效性檢測(ping)。檢測到無效連接將會被移除。

false

業務量很大時候建議設置為false,減少一次ping的開銷。

jmxEnabled

是否開啟JMX監控

true

建議開啟,請注意應用本身也需要開啟。

空閑Jedis對象檢測由下列四個參數組合完成。

表 2. 空閑資源檢測相關參數

名稱

說明

默認值

建議

testWhileIdle

是否在空閑資源監測時通過ping命令監測連接有效性,無效連接將被銷毀。

false

true

timeBetweenEvictionRunsMillis

空閑資源的檢測周期(單位為毫秒)

-1(不檢測)

建議設置,周期自行選擇,也可以默認也可以使用下方JedisPoolConfig 中的配置。

minEvictableIdleTimeMillis

資源池中資源的最小空閑時間(單位為毫秒),達到此值后空閑資源將被移除。

1,800,000(即30分鐘)

可根據自身業務決定,一般默認值即可,也可以考慮使用下方JeidsPoolConfig中的配置。

numTestsPerEvictionRun

做空閑資源檢測時,每次檢測資源的個數。

3

可根據自身應用連接數進行微調,如果設置為 -1,就是對所有連接做空閑監測。

為了方便使用,Jedis提供了JedisPoolConfig,它繼承了GenericObjectPoolConfig在空閑檢測上的一些設置。

public class JedisPoolConfig extends GenericObjectPoolConfig {
  public JedisPoolConfig() {
    setTestWhileIdle(true);
    setMinEvictableIdleTimeMillis(60000);
    setTimeBetweenEvictionRunsMillis(30000);
    setNumTestsPerEvictionRun(-1);
    }
}
說明

可以在org.apache.commons.pool2.impl.BaseObjectPoolConfig中查看全部默認值。

關鍵參數設置建議

maxTotal(最大連接數)

想合理設置maxTotal(最大連接數)需要考慮的因素較多,如:

  • 業務希望的Redis并發量;

  • 客戶端執行命令時間;

  • Redis資源,例如nodes (如應用ECS個數等) * maxTotal不能超過Redis的最大連接數(可在實例詳情頁面查看);

  • 資源開銷,例如雖然希望控制空閑連接,但又不希望因為連接池中頻繁地釋放和創建連接造成不必要的開銷。

假設一次命令時間,即borrow|return resource加上Jedis執行命令 ( 含網絡耗時)的平均耗時約為1ms,一個連接的QPS大約是1s/1ms = 1000,而業務期望的單個Redis的QPS是50000(業務總的QPS/Redis分片個數),那么理論上需要的資源池大小(即MaxTotal)是50000 / 1000 = 50。

但事實上這只是個理論值,除此之外還要預留一些資源,所以maxTotal可以比理論值大一些。這個值不是越大越好,一方面連接太多會占用客戶端和服務端資源,另一方面對于Redis這種高QPS的服務器,如果出現大命令的阻塞,即使設置再大的資源池也無濟于事。

maxIdle與minIdle

maxIdle實際上才是業務需要的最大連接數,maxTotal 是為了給出余量,所以 maxIdle 不要設置得過小,否則會有new Jedis(新連接)開銷,而minIdle是為了控制空閑資源檢測。

連接池的最佳性能是maxTotal=maxIdle,這樣就避免了連接池伸縮帶來的性能干擾。如果您的業務存在突峰訪問,建議設置這兩個參數的值相等;如果并發量不大或者maxIdle設置過高,則會導致不必要的連接資源浪費。

您可以根據實際總QPS和調用Redis的客戶端規模整體評估每個節點所使用的連接池大小。

使用監控獲取合理值

在實際環境中,比較可靠的方法是通過監控來嘗試獲取參數的最佳值。可以考慮通過JMX等方式實現監控,從而找到合理值。

常見問題

資源不足

下面兩種情況均屬于無法從資源池獲取到資源。

  • 超時:

    redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    …
    Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)
  • blockWhenExhausted 為false,因此不會等待資源釋放:

    redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    …
    Caused by: java.util.NoSuchElementException: Pool exhausted
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:464)

此類異常的原因不一定是資源池不夠大,請參見關鍵參數設置建議中的分析。建議從網絡、資源池參數設置、資源池監控(如果對JMX監控)、代碼(例如沒執行jedis.close())、慢查詢、DNS等方面進行排查。

預熱JedisPool

由于一些原因(如超時時間設置較小等),項目在啟動成功后可能會出現超時。JedisPool定義最大資源數、最小空閑資源數時,不會在連接池中創建Jedis連接。初次使用時,池中沒有資源使用則會先新建一個new Jedis,使用后再放入資源池,該過程會有一定的時間開銷,所以建議在定義JedisPool后,以最小空閑數量為基準對JedisPool進行預熱,示例如下:

List<Jedis> minIdleJedisList = new ArrayList<Jedis>(jedisPoolConfig.getMinIdle());

for (int i = 0; i < jedisPoolConfig.getMinIdle(); i++) {
    Jedis jedis = null;
    try {
        jedis = pool.getResource();
        minIdleJedisList.add(jedis);
        jedis.ping();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {
    }
}

for (int i = 0; i < jedisPoolConfig.getMinIdle(); i++) {
    Jedis jedis = null;
    try {
        jedis = minIdleJedisList.get(i);
        jedis.close();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {
    
    }
}

如有其它報錯,請參見常見報錯