翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
Lettuce クライアント設定 (Valkey および Redis OSS)
このセクションでは、推奨される Java と Lettuce の設定オプションと、それらを ElastiCache クラスターに適用する方法について説明します。
このセクションの推奨事項は、Lettuce バージョン 6.2.2 でテスト済みです。
Java DNS キャッシュ TTL
Java 仮想マシン (JVM) は DNS 名参照をキャッシュします。JVM がホスト名を IP アドレスに変換するとき、time-to-live (TTL) と呼ばれる指定期間 IP アドレスをキャッシュします。
TTL 値の選択は、レイテンシーおよび変化に対する応答性と間のトレードオフです。TTL を短くすると、DNS リゾルバーはクラスターの DNS の更新をより早く認識します。これにより、クラスターで実行される置換やその他のワークフローにアプリケーションがより迅速に応答できるようになります。ただし、TTL が低すぎると、クエリの量が増え、それによってアプリケーションのレイテンシーが増加する可能性があります。絶対的に正しい TTL 値は存在しませんが、TTL 値を設定するときは、変更が有効になるまで待つことができる時間の長さについて検討する必要があります。
ElastiCache ノードは、変更される可能性がある DNS 名を使用するため、5~10 秒の低い TTL 値で JVM を設定することをお勧めします。これにより、ノードの IP アドレスが変更されたときに、アプリケーションは DNS エントリに対して再度クエリを実行することで、リソースの新しい IP アドレスを取得し、使用できるようになります。
一部の Java 設定では JVM のデフォルトの TTL が設定されるため、JVM が再起動されるまで、DNS エントリが更新されることはありません。
JVM TTL を設定する方法の詳細については、「JVM TTL を設定する方法」を参照してください。
Lettuce のバージョン
Lettuce のバージョン 6.2.2 以降の使用をお勧めします。
エンドポイント
クラスターモードが有効なクラスターを使用している場合は、redisUri
をクラスター設定エンドポイントに設定します。この URI の DNS ルックアップは、クラスターで使用可能なすべてのノードのリストを返し、クラスターの初期化中にそれらのノードの 1 つにランダムに解決されます。トポロジ更新の仕組みの詳細については、このトピックで後述する「DynamicRefreshResources」を参照してください。
SocketOption
KeepAlive
接続タイムアウトは
ClusterClientOption:クラスターモードが有効なクライアントオプション
接続が失われたときは AutoReconnect
CommandTimeout
NodeFilter
例えば、フェイルオーバーが完了してクラスターが回復プロセスを開始した後、clusterTopology が更新されている間、ダウンしているノードがトポロジから完全に削除されるまで、クラスターバスノードマップにそれが FAIL ノードとして短期間リストされます。この間、Lettuce クライアントはそのノードを正常なノードと見なし、継続的に接続します。そのため、再試行を使い果たすとエラーが発生します。
例:
final ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder() ... // other options .nodeFilter(it -> ! (it.is(RedisClusterNode.NodeFlag.FAIL) || it.is(RedisClusterNode.NodeFlag.EVENTUAL_FAIL) || it.is(RedisClusterNode.NodeFlag.HANDSHAKE) || it.is(RedisClusterNode.NodeFlag.NOADDR))) .validateClusterNodeMembership(false) .build(); redisClusterClient.setOptions(clusterClientOptions);
注記
ノードフィルタリングは、DynamicRefreshSources を true に設定して使用するのが最適です。そうしないと、1 つの問題のあるシードノードからトポロジビューを取得すると、一部のシャードのプライマリノードに障害が発生していると見なされ、このプライマリノードは除外され、スロットがカバーされなくなります。(DynamicRefreshSources が true の場合に) 複数のシードノードが存在すると、この問題が発生する可能性が低くなります。これは、新しく昇格したプライマリとのフェイルオーバー後に、少なくとも一部のシードノードでトポロジビューを更新する必要があるためです。
ClusterTopologyRefreshOptions: クラスターモード対応クライアントのクラスタートポロジ更新を制御するオプション
注記
クラスターモードが無効なクラスターは、クラスター検出コマンドをサポートしていないため、すべてのクライアントの動的トポロジー検出機能と互換性があるわけではありません。
ElastiCache で無効になっているクラスターモードは Lettuce の MasterSlaveTopologyRefresh
と互換性がありません。代わりに、クラスタモードが無効になっている場合は、StaticMasterReplicaTopologyProvider
を設定し、クラスターの読み取りと書き込みのエンドポイントを提供します。
クラスターモードが無効なクラスターとの接続の詳細については、「Valkey または Redis OSS (クラスターモードが無効) クラスターのエンドポイントを検索する (コンソール)」を参照してください。
Lettuce の動的トポロジー検出機能を使いたい場合は、既存のクラスターと同じシャード構成でクラスターモードが有効なクラスターを作成できます。ただし、クラスターモードが有効なクラスターでは、高速フェールオーバーをサポートするために、少なくとも 3 つのシャードと 1 つのレプリカを構成することをお勧めします。
enablePeriodicRefresh
このオプションを有効にすると、このジョブをバックグラウンドタスクに追加することで、クラスタートポロジの更新に伴うレイテンシを減らすことができます。トポロジの更新はバックグラウンドジョブで実行されますが、多数のノードがあるクラスターでは多少遅くなる可能性があります。これは、すべてのノードが最新のクラスタービューを取得するためにそれらのビューに対してクエリが実行されているためです。大規模なクラスターを実行する場合は、この時間を長くすることをお勧めします。
enableAllAdaptiveRefreshTriggers
closeStaleConnections
dynamicRefreshResources
動的更新を使用すると、検出されたすべてのノードにクラスタートポロジを照会し、最も正確なクラスタービューを選択しようと試みます。false に設定すると、最初のシードノードのみがトポロジ検出のソースとして使用され、クライアント数は最初のシードノードについてのみ取得されます。無効になっている場合、クラスター設定エンドポイントが障害の発生したノードに解決されたとき、クラスタービューを更新しようとすると失敗し、例外が発生します。このシナリオは、障害が発生したノードのエントリがクラスター設定エンドポイントから削除されるまでに時間がかかるときに発生する可能性があります。そのため、設定エンドポイントは、障害が発生したノードに短期間ランダムに解決できます。
ただし、有効にすると、クラスタービューから受信したすべてのクラスターノードを使用して、現在のビューについてクエリを実行します。障害が発生したノードをそのビューから除外するので、トポロジ更新は成功します。ただし、dynamicRefreshSources が true の場合、Lettuce はすべてのノードにクエリを実行してクラスタービューを取得し、結果を比較します。そのため、多数のノードを持つクラスターではコストがかかる可能性があります。多数のノードがあるクラスターでは、この機能をオフにすることをお勧めします。
final ClusterTopologyRefreshOptions topologyOptions = ClusterTopologyRefreshOptions.builder() .enableAllAdaptiveRefreshTriggers() .enablePeriodicRefresh() .dynamicRefreshSources(true) .build();
ClientResources
DnsResolver
reconnectDelay
ClientResources clientResources = DefaultClientResources.builder() .dnsResolver(new DirContextDnsResolver()) .reconnectDelay( Delay.fullJitter( Duration.ofMillis(100), // minimum 100 millisecond delay Duration.ofSeconds(10), // maximum 10 second delay 100, TimeUnit.MILLISECONDS)) // 100 millisecond base .build();
Timeouts
コマンドのタイムアウトよりも低い接続タイムアウト値を使用してください。Lettuce はレイジー接続確立を使用します。そのため、接続タイムアウトがコマンドタイムアウトよりも大きい場合、Lettuce が異常なノードへの接続を試みてコマンドのタイムアウトが常に超過すると、トポロジ更新後に障害が一定期間持続する可能性があります。
異なるコマンドに対しては動的コマンドタイムアウトを使用してください。コマンドの想定期間に基づいてコマンドタイムアウトを設定することをお勧めします。例えば、FLUSHDB、FLUSHALL、KEYS、SMEMBERS、Lua スクリプトなど、複数のキーを反復処理するコマンドにはタイムアウトを長く設定します。SET、GET、HSET など、1 つのキーコマンドではタイムアウトを短くします。
注記
次の例で設定されているタイムアウトは、最大 20 バイトの長さのキーと値で SET/GET コマンドを実行したテスト用です。コマンドが複雑な場合や、キーと値が大きい場合は、処理時間が長くなる可能性があります。タイムアウトは、アプリケーションのユースケースに基づいて設定する必要があります。
private static final Duration META_COMMAND_TIMEOUT = Duration.ofMillis(1000); private static final Duration DEFAULT_COMMAND_TIMEOUT = Duration.ofMillis(250); // Socket connect timeout should be lower than command timeout for Lettuce private static final Duration CONNECT_TIMEOUT = Duration.ofMillis(100); SocketOptions socketOptions = SocketOptions.builder() .connectTimeout(CONNECT_TIMEOUT) .build(); class DynamicClusterTimeout extends TimeoutSource { private static final Set<ProtocolKeyword> META_COMMAND_TYPES = ImmutableSet.<ProtocolKeyword>builder() .add(CommandType.FLUSHDB) .add(CommandType.FLUSHALL) .add(CommandType.CLUSTER) .add(CommandType.INFO) .add(CommandType.KEYS) .build(); private final Duration defaultCommandTimeout; private final Duration metaCommandTimeout; DynamicClusterTimeout(Duration defaultTimeout, Duration metaTimeout) { defaultCommandTimeout = defaultTimeout; metaCommandTimeout = metaTimeout; } @Override public long getTimeout(RedisCommand<?, ?, ?> command) { if (META_COMMAND_TYPES.contains(command.getType())) { return metaCommandTimeout.toMillis(); } return defaultCommandTimeout.toMillis(); } } // Use a dynamic timeout for commands, to avoid timeouts during // cluster management and slow operations. TimeoutOptions timeoutOptions = TimeoutOptions.builder() .timeoutSource( new DynamicClusterTimeout(DEFAULT_COMMAND_TIMEOUT, META_COMMAND_TIMEOUT)) .build();