Tair (Redis OSS-compatible) インスタンスでは、ネットワークジッター、サービス中断、またはサーバー負荷により、一時的なエラーが発生する可能性があります。これらのエラーを適切に処理するために、ご利用のクライアントライブラリで自動リトライメカニズムを設定してください。
一時的なエラーの原因
| 原因 | 影響 |
|---|---|
| マスター・レプリカ スイッチオーバー | Tair はノードの健全性を監視し、マスターノードが失敗するとスイッチオーバーをトリガーします。クライアントは数秒以内の一時的な切断と、30 秒以内の読み取り専用状態を経験する可能性があります。読み取り専用状態は、データ損失とデュアルライトを防ぎます。詳細については、「高可用性」をご参照ください。 |
| スロークエリ | O(N) の時間計算量を持つ操作は、他のリクエストをブロックし、同時クライアント操作で一時的な失敗を引き起こす可能性があります。 |
| ネットワークの問題 | クライアントとサーバー間のネットワークジッターとデータ再送は、断続的なリクエストの失敗を引き起こします。 |
リトライのベストプラクティス
べき等な操作のみをリトライ
コマンド実行のどの段階でもタイムアウトが発生する可能性があります。
コマンドがサーバーに到達していない。
コマンドはサーバーに到達したが、実行がタイムアウトした。
コマンドはサーバーで実行されたが、レスポンスがタイムアウトした。
リトライされた操作は複数回実行される可能性があるため、べき等な操作のみをリトライしてください。
べき等 -- SET a b: このコマンドを複数回実行しても、常に同じ結果が生成されます。
非べき等 -- LPUSH mylist a: このコマンドを複数回実行すると、重複する a 要素が mylist に追加されます。
適切なリトライ回数と間隔の設定
ご利用のワークロードに基づいて、リトライ回数と間隔を設定してください。
リトライ回数が少なすぎる、または間隔が長すぎる場合: アプリケーションは、短い一時的なエラー中に操作を完了できない可能性があります。
リトライ回数が多すぎる、または間隔が短すぎる場合: アプリケーションは過剰なリソースを消費し、サーバーに過負荷をかける可能性があります。
| 戦略 | 説明 |
|---|---|
| 即時リトライ | 遅延なしでリトライします。ミリ秒以内に解決すると予想されるエラーにのみ適しています。 |
| 固定間隔リトライ | リトライ間に固定の期間待機します。多くのクライアントが同時にリトライすると、リクエストスパイクを引き起こす可能性があります。 |
| 指数バックオフ | 各試行後に待機時間を倍にします。リトライを時間的に分散させ、サーバー負荷を軽減します。 |
| ランダム化バックオフ | バックオフ間隔にランダムなジッターを追加します。共有された障害イベントの後、複数のクライアントが同時にリトライするのを防ぎます。 |
リトライのネストの回避
リトライのネスト (リトライ操作が別のリトライループをトリガーする場合) は、繰り返されるリトライまたは無制限のリトライを引き起こす可能性があります。アプリケーションスタックの単一レイヤーでリトライロジックを実装してください。
リトライ失敗のログ記録
WARN レベルでリトライログを生成します。ログノイズを避けるため、個々の試行時ではなく、最終的なリトライが失敗した場合にのみログを記録してください。
Jedis
Jedis 4.0.0 以降を使用してください。以下の例では Jedis 5.0.0 を使用しています。
ご利用の pom.xml ファイルに依存関係を追加してください。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.0.0</version>
</dependency>プロキシモードの標準またはクラスターインスタンス (JedisPool)
プロキシモードの標準インスタンスまたはクラスターインスタンスには、PooledConnectionProvider と UnifiedJedis を使用します。
この例では、SET コマンドを 10 秒以内に最大 5 回、指数関数的に増加する待機時間でリトライします。すべてのリトライが失敗した場合、例外がスローされます。
PooledConnectionProvider provider = new PooledConnectionProvider(HostAndPort.from("127.0.0.1:6379"));
int maxAttempts = 5; // 最大リトライ試行回数
Duration maxTotalRetriesDuration = Duration.ofSeconds(10); // 最大合計リトライ期間
UnifiedJedis jedis = new UnifiedJedis(provider, maxAttempts, maxTotalRetriesDuration);
try {
System.out.println("set key: " + jedis.set("key", "value"));
} catch (Exception e) {
// 操作は maxAttempts 回のリトライ後、または maxTotalRetriesDuration が経過した後に失敗しました。
e.printStackTrace();
}| パラメーター | 例の値 | 説明 |
|---|---|---|
maxAttempts | 5 | 最大リトライ試行回数。 |
maxTotalRetriesDuration | 10 秒 | すべてのリトライ試行における最大合計期間。この期間が超過すると、maxAttempts に達していなくてもリトライは停止します。 |
直接接続モードのクラスターインスタンス (JedisCluster)
直接接続モードのクラスターインスタンスには、JedisCluster を使用します。maxAttempts パラメーターはリトライ試行回数を設定します。デフォルト値は 5 です。最大試行回数後に操作が失敗した場合、例外がスローされます。
HostAndPort hostAndPort = HostAndPort.from("127.0.0.1:30001");
int connectionTimeout = 5000;
int soTimeout = 2000;
int maxAttempts = 5;
ConnectionPoolConfig config = new ConnectionPoolConfig();
JedisCluster jedisCluster = new JedisCluster(hostAndPort, connectionTimeout, soTimeout, maxAttempts, config);
try {
System.out.println("set key: " + jedisCluster.set("key", "value"));
} catch (Exception e) {
// 操作は maxAttempts 回のリトライ後に失敗しました。
e.printStackTrace();
}| パラメーター | 例の値 | デフォルト | 説明 |
|---|---|---|---|
connectionTimeout | 5000 | -- | 接続タイムアウト (ミリ秒)。 |
soTimeout | 2000 | -- | ソケットタイムアウト (ミリ秒)。 |
maxAttempts | 5 | 5 | 失敗時の最大リトライ試行回数。 |
Redisson
Redisson は、リトライ動作を制御するための 2 つのパラメーターを提供します。
| パラメーター | デフォルト | 説明 |
|---|---|---|
retryAttempts | 3 | リトライ試行回数。 |
retryInterval | 1500 ms | リトライ間の間隔 (ミリ秒)。 |
Config config = new Config();
config.useSingleServer()
.setTimeout(1000)
.setRetryAttempts(3)
.setRetryInterval(1500) // ms
.setAddress("redis://127.0.0.1:6379");
RedissonClient connect = Redisson.create(config);StackExchange.Redis
StackExchange.Redis は、接続リトライのみをサポートし、コマンドレベルのリトライはサポートしていません。connectRetry パラメーターを使用して、再接続試行回数を設定してください。
var conn = ConnectionMultiplexer.Connect("redis0:6380,redis1:6380,connectRetry=3");| パラメーター | 例の値 | 説明 |
|---|---|---|
connectRetry | 3 | 初期接続をリトライする回数。 |
コマンドレベルのリトライロジックには、Polly などのレジリエンスライブラリを使用して、個々のコマンドをリトライポリシーでラップしてください。
Lettuce
Lettuce は、タイムアウト後に個々のコマンドをリトライするためのパラメーターを提供していません。代わりに、2 つの実行信頼性モードをサポートしています。
| モード | 動作 |
|---|---|
| At-most-once | 各コマンドは最大 1 回実行されます。クライアントが切断され、再接続した場合、保留中のコマンドが失われる可能性があります。 |
| At-least-once (デフォルト) | 各コマンドは少なくとも 1 回実行されます。クライアントは、正常な実行を保証するためにコマンドをリトライします。クライアントがリトライ中にマスター・レプリカ スイッチオーバーが発生した場合、リトライコマンドが蓄積される可能性があります。スイッチオーバーが完了した後、インスタンスの CPU 使用率が急増する可能性があります。 |
autoReconnect 設定は、実行モードを決定します。
clientOptions.isAutoReconnect() ? Reliability.AT_LEAST_ONCE : Reliability.AT_MOST_ONCE;詳細については、「Client-Options」および「Command execution reliability」をご参照ください。