JedisPool パラメーターを設定すると、Redis のパフォーマンスが向上します。 このドキュメントでは、JedisPool の使用方法とリソースプールパラメーターの設定方法について説明します。 また、JedisPool を最適化するための推奨パラメーター設定も提供します。
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 indicates the instance IP address. redisPort indicates the instance port. redisPassword indicates the password of the instance. The timeout parameter indicates both the connection timeout and the read/write timeout.
JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort, timeout, redisPasswor//d);
//Run the command as follows:
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
// Specific commands
jedis.executeCommand()
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
//In JedisPool mode, the Jedis resource will be returned to the resource pool.
if (jedis ! = null)
jedis.close();
}
パラメーターの説明
Jedis 接続は、接続プール内の JedisPool によって管理されるリソースです。 JedisPool はスレッドセーフな接続プールであり、すべてのリソースを管理可能な範囲内に維持できます。 GenericObjectPoolConfig パラメーターを適切に設定すると、Redis のパフォーマンスが向上し、リソース消費が削減されます。 次の 2 つの表では、いくつかの重要なパラメーターについて説明し、パラメーターの設定に関する推奨事項を示します。
パラメーター | 説明 | デフォルト値 | 推奨事項 |
---|---|---|---|
maxTotal | このプールから割り当てることができる接続の最大数。 | 8 | 「主要なパラメーター設定の推奨事項」をご参照ください 。 |
maxIdle | 追加の接続がリリースされることなく、プール内でアイドル状態を維持できる最大接続数。 | 8 | 「主要なパラメーター設定の推奨事項」をご参照ください 。 |
minIdle | 追加の接続を作成せずに、プール内でアイドル状態を維持できる最小接続数。 | 0 | 「主要なパラメーター設定の推奨事項」をご参照ください 。 |
blockWhenExhausted | リソースプールが使い果たされたときに呼び出し元が待機する必要があるかどうか。 以下の maxWaitMillis は、値が "true" である場合にのみ有効です。 | true | デフォルト値を使用することを推奨します。 |
maxWaitMillis | 接続が使用できないときに呼び出し元が待機する必要がある最大ミリ秒数。 | -1 は、タイムアウトしないことを意味します。 | デフォルト値は推奨されません。 |
testOnBorrow | 接続がプールから借用される前に ping コマンドを使用して検証されるかどうか。 接続が無効であることが判明した場合、その接続はプールから削除されます。 | false | ビジネストラフィックが多い場合は、ping テストの消費を削減するために false に設定することを推奨します。 |
testOnReturn | 接続がプールに返される前に ping コマンドを使用して検証されるかどうか。 接続が無効であることが判明した場合、その接続はプールから削除されます。 | false | ビジネストラフィックが多い場合は、ping テストの消費を削減するために false に設定することを推奨します。 |
jmxEnabled | JMX 監視を有効にするかどうか。 | true | JMX 監視を有効にすることを推奨します。 アプリケーション自体も有効にする必要があることに注意してください。 |
アイドル状態の Jedis オブジェクト検出は、次の 4 つのパラメーターで構成されます。 testWhileIdle がこの機能の切り替えです。
名称 | 説明 | デフォルト値 | 推奨事項 |
---|---|---|---|
testWhileIdle | アイドルリソースの検出を有効にするかどうか。 | false | true |
timeBetweenEvictionRunsMillis | アイドルオブジェクト Evictor スレッドの実行間でスリープするミリ秒数。 | -1 は、アイドル状態のオブジェクト Evictor スレッドが実行されないことを意味します。 | このパラメーターを設定して、独自のサイクル選択を行うことを推奨します。 または、JedisPoolConfig のデフォルト設定を使用できます。 |
minEvictableIdleTimeMillis | アイドル状態のオブジェクト Evictor (存在する場合) によるエビクションの対象となる前に、オブジェクトがプール内でアイドル状態になる可能性がある最小時間。 | 180000 (30 分) | デフォルト値はほとんどの場合に適しています。 ビジネスシナリオに基づいて、 JeidsPoolConfig の設定を使用することもできます。 |
numTestsPerEvictionRun | アイドル状態のオブジェクト Evictor スレッド (存在する場合) の各実行中に検査するオブジェクトの数。 | 3 | アプリケーションの接続数に応じて変更できます。 この値が -1 に設定されている場合、すべての接続でアイドル検証が実行されます。 |
参考のために Jedis は、アイドル接続の検証で、いくつかの設定を GenericObjectPoolConfig と共有する JedisPoolConfig を提供しています。
public class JedisPoolConfig extends GenericObjectPoolConfig {
public JedisPoolConfig() {
// defaults to make your life with connection pool easier :)
setTestWhileIdle(true);
//
setMinEvictableIdleTimeMillis(60000);
//
setTimeBetweenEvictionRunsMillis(30000);
setNumTestsPerEvictionRun(-1);
}
}
主要なパラメーター設定の推奨事項
maxTotal:接続の最大数。
maxTotal を適切に設定するには、次の要因を考慮する必要があります。
- ビジネスに必要な Redis の同時接続数。
- クライアントがコマンドを実行するのにかかる時間。
- Redis リソースの制限。 たとえば、maxTotal にノード (アプリケーション) の数を乗算した積は、Redis で許可されている接続の最大数よりも小さくなければなりません。
- 接続の作成とリリースのコスト。 各リクエストで作成およびリリースされる接続の数が多い場合、作成およびリリース処理に大きな負担がかかります。
コマンドを実行してリソースを取得する時間は、リソースを借用して返す時間、JedisPool がコマンドを実行する時間、およびネットワーク接続の時間で構成されます。 リソースを取得するコマンドを実行する平均時間が約 1 ミリ秒、接続の QPS が約 1000、ビジネスで予想される QPS が50000 である場合、理論的には必要なプールサイズは 50 (50,000 / 1,000 = 50) になります。
しかし、これは単なる理論値です。 一部のリソースを予約するために、 maxTotal パラメーターの値を理論値より大きくすることができます。 ただし、この値が大きすぎると、接続がクライアントとサーバーのリソースを大量に消費します。 一方、Redis のように QPS が高いサーバーでは、コマンドのブロックがある場合、大きなリソースプールでもこの問題の解決には役立ちません。
maxIdle と minIdle
maxIdle はビジネスに必要な接続の実際の最大数であり、 maxTotal にはアイドル接続の数が余剰として含まれます。 負荷の高いシステムで maxIdle の設定が低すぎると、要求を処理するために new Jedis
(追加接続) が作成されます。 したがって、minIdle は、プールに保持する必要がある確立された接続の最小数を指定するように設定されます。
接続プールは、次の場合に最高のパフォーマンスに達します。 maxTotal = maxIdle 。 このように、パフォーマンスは接続プールのスケーリングの影響を受けません。 ただし、同時接続の数が少ない場合、または maxTotal パラメーターの設定が高すぎると、接続リソースが無駄になります。
実際の合計 QPS と Redis を呼び出すクライアントの数に基づいて、各ノードで使用される接続プールサイズを見積もることができます。
監視ツールを使用して適切な値を取得する
監視ツールを使用して最適なパラメーター値を取得する方が、より信頼性は高くなります。 JMX 監視または他の監視ツールを使用して、最適な値を見つけることができます。
よくある質問
不十分なリソース
次の 2 つの場合、リソースプールからリソースを取得できません。
- タイムアウト:
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 に設定すると、borrowMaxWaitMillis で指定された時間は使用されず、borrowObject 呼び出しは、アイドル接続が使用可能になるまでブロックされます。
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 {
}
}