Jedis是Redis官方提供的java客戶端,是一款便于使用和性能較佳的redis客戶端工具。 其他說明可以參考Jedis文檔。
合理的Jedis連接池參數設置能夠有效地提升客戶端使用Redis性能。本文將對Jedis的使用和連接池的參數進行說明,并提供優化配置的建議。
使用方法
以 jedis 4.3.1版本為例,下面是maven依賴配置:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>
Jedis使用Apache Commons-pool2對連接池進行管理,在定義JedisPool時需注意其關鍵參數GenericObjectPoolConfig(連接池)。該參數的使用示例如下,其中的參數的說明請參見下文。
GenericObjectPoolConfig<Jedis> config = new GenericObjectPoolConfig<>();
config.setMaxTotal(100);
config.setMaxIdle(50);
config.setMinIdle(5);
config.setTestWhileIdle(true);
....
Jedis的初始化方法如下:
JedisPool pool = new JedisPool(config, host, port, timeout, password);//創建連接池
try (Jedis jedis = pool.getResource()) { //獲取連接,執行完自動釋放連接
//利用jedis客戶端執行命令
} catch (Exception e) {
e.printStackTrace();
}
pool.close();//關閉連接池
參數說明
Jedis連接就是連接池中JedisPool管理的資源,JedisPool保證連接在一個可控范圍內,并且保障線程安全。使用合理的GenericObjectPoolConfig配置能夠提升Redis的服務性能,降低資源開銷。下列兩表將對一些重要參數進行說明,并提供設置建議。
表1. GenericObjectPoolConfig參數說明
參數 說明 默認值 建議 maxTotal 連接池的最大連接數 8 參考下面的參數設置建議 maxIdle 連接池的最大空閑連接數 8 參考下面的參數設置建議 minIdle 連接池確保的最少空閑連接,不足的會新建連接 0 參考下面的參數設置建議 blockWhenExhausted 當連接池的連接用盡后,獲取新連接是否會阻塞等待。
true: 會阻塞直到獲取新連接或maxWaitMillis時間到了, 拋出異常.
false: 會直接拋出異常
true 建議使用默認值 maxWaitMillis 當連接池的連接用盡后,獲取連接的最大等待時間(單位毫秒),-1表示一直阻塞 -1 建議設置一個合理的超時時間,避免出現當連接池用盡后,應用阻塞不響應的情況 testOnBorrow 每次向連接池獲取連接時是否做連接有效性檢測(發送PING請求)。無效連接會被釋放 false 建議使用默認值。設為true相當于在每個命令執行完前先發一個PING命令,對高并發請求大應用的性能有影響。
對于業務可用性要求比較高的場景,可以設為true,可以保證連接有效的。
testOnReturn 每次向連接池歸還連接時是否做連接有效性檢測(發送PING請求),無效連接會被釋放 false 建議使用默認值。設為true相當于在每個命令執行完后再發一個PING命令,對高并發請求大應用的性能有影響。 lifo 連接池管理連接的方式是否使用LIFO方式
true使用LIFO(后進先出)方式
false使用FIFO(先進先出)方式
true 建議使用默認值。 fairness 并發獲取連接時,是否按并發的先后順序從連接池獲取 false 建議使用默認值。 false的情況,性能更佳a jmxEnabled 是否開啟jmx監控 true 建議使用默認值,同時應用也需要開啟 testWhileIdle 是否檢測空閑連接的有效性,無效連接會被釋放
只在timeBetweenEvictionRunsMillis > 0時有效
false 建議使用true。也可使用JedisPoolConfig。 timeBetweenEvictionRunsMillis 空閑連接的檢測周期(單位毫秒),-1表示不開啟空閑連接檢測 -1 建議建議設置,周期自行選擇。也可使用JedisPoolConfig minEvictableIdleTimeMillis 最小空閑時間(單位毫秒)。空閑連接檢測時,如果連接在最小空閑時間內都沒有被獲取使用,則會被釋放。-1表示不釋放,
只在timeBetweenEvictionRunsMillis > 0有效1800000(30分鐘) 根據業務決定,一般使用默認值即可。也可使用JedisPoolConfig的配置 numTestsPerEvictionRun 檢測空閑連接時,每次檢測的連接數,如果為負數-n,則表示檢測1/n個連接 3 可根據業務需求設置。?
Jedis也提供了參考的JedisPoolConfig類。由于jedis、spring data redis等SDK默認使用的是JedisPoolConfig類,而JedisPoolConfig類繼承自GenericKeyedObjectPoolConfig類。JedisPoolConfig為了方便使用在構造函數中設置了一些參數,具體如下:
public class JedisPoolConfig extends GenericObjectPoolConfig<Jedis> {
public JedisPoolConfig() {
// defaults to make your life with connection pool easier :)
setTestWhileIdle(true);
setMinEvictableIdleTime(Duration.ofMillis(60000));
setTimeBetweenEvictionRuns(Duration.ofMillis(30000));
setNumTestsPerEvictionRun(-1);
}
}
這些參數對JedisPool連接池的具體含義是:JedisPool連接池默認最多有8個連接,最多有8個空閑連接,同時開啟空閑連接檢測,每30s檢測一次(且會通過發送PING命令,檢測連接的有效性),如果有連接60s內仍然處于空閑狀態(60s內一直沒有使用)或無效(連接異常),該連接就會被釋放,一次釋放一個。
參數設置建議
maxTotal、maxIdle、minIdle的關系
這些參數在連接池中的含義是:maxTotal是連接池的容量,包括空閑連接和使用中的連接。將連接歸還給連接池時,如果空閑連接數超過maxIdle,會被直接釋放。同時連接池還要保證其中至少要有minIdle個空閑連接,如果不足也會新建連接加入其中。
maxTotal
想合理設置maxTotal(最大連接數)需要考慮的因素較多,如:
- 業務要求的Redis并發量;
- 命令執行時間;
- Redis連接數限制,例如 客戶端連接池個數 * maxTotal不能超過Redis的最大連接數
- 資源開銷, 不希望有多余的空閑連接浪費資源,但也不希望連接不夠導致創建連接造成不必要的開銷
假設一次命令時間,包括獲取連接、發送請求到得到響應(含網絡耗時)的平均耗時約為1ms。 一個連接的QPS大約是1sec / 1ms = 1000,而業務期望的單個Redis的QPS是10000,那么理論上需要的連接池大小(即MaxTotal)是10000 / 1000 = 10。
但理論值也僅需參考,因為實際的運行情況和業務壓力是動態變化的。 可能遇到突發的高壓力的場景,需要更多的TPS。也可能Redis遇到出現大命令導致阻塞,即使設置再大的資源池也無濟于事。
maxIdle和minIdle
maxIdle和minIdle是最影響業務的參數, 分別控制可用連接數的上下限。
連接池的最佳性能是maxTotal = maxIdle ,這樣就避免了連接池伸縮帶來的性能干擾。如果您的業務存在突峰壓力,建議設置這兩個參數的值相等;如果redis請求的壓力不大,則會導致不必要的連接資源浪費。
總的來說, 可以根據實際總QPS和調用Redis的客戶端規模整體評估每個節點所使用的連接池大小。
使用監控獲取合理值
在實際環境中,比較可靠的方法是通過監控來嘗試獲取參數的最佳值。可以考慮通過JMX等方式實現監控,從而找到合理值。