このページでは、Memorystore for Redis Cluster の最適な使用に関するガイダンスを提供します。また、回避すべき潜在的な問題についても説明します。
メモリ管理のベスト プラクティス
このセクションでは、Memorystore for Redis Cluster がアプリケーションで効率的に動作するように、インスタンスのメモリを管理するための戦略について説明します。
メモリ管理のコンセプト
書き込み負荷 - Redis クラスタでキーを追加または更新するボリュームと速度。書き込み負荷は、Redis のユースケースとアプリケーションの使用パターンに応じて、通常から非常に高い範囲で変化します。
エビクション ポリシー - Memorystore for Redis Cluster は、
volatile-lruエビクション ポリシーを使用します。EXPIRE コマンドなどのコマンドを使用して、キーのエビクションを設定できます。
書き込み負荷が通常のクラスタをモニタリングする
/cluster/memory/maximum_utilization 指標を表示します。/cluster/memory/maximum_utilization が 100% 以下の場合、通常の書き込み負荷を使用すると、Redis クラスタは適切に動作します。
ただし、メモリ使用量が 100% に近づき、データ使用量が増加すると予想される場合は、新しいデータを格納できるようにクラスタサイズをスケールアップする必要があります。
書き込み負荷が高いクラスタをモニタリングする
/cluster/memory/maximum_utilization 指標を表示します。書き込み負荷が高い場合、クラスタは次のしきい値でパフォーマンスの問題が発生する可能性があります。
書き込み負荷が非常に高い場合、
/cluster/memory/maximum_utilizationが 65% 以上になると問題が発生する可能性があります。書き込み負荷が中程度に高い場合、
/cluster/memory/maximum_utilizationが 85% 以上になると問題が発生する可能性があります。
このような場合は、クラスタサイズをスケールアップしてパフォーマンスを向上させる必要があります。
問題が発生した場合や、インスタンスの書き込み負荷が高いと思われる場合は、 Google Cloud サポートにお問い合わせください。
シャードをスケーリングする
インスタンス内のシャード数 をスケーリングする場合は、書き込みが少ない期間にスケーリングする必要があります。書き込み負荷が高い期間にスケーリングすると、レプリケーションまたはスロット移行によるメモリのオーバーヘッドが原因で、インスタンスにメモリの負荷がかかります。
Redis のユースケースでキーのエビクションを使用している場合、クラスタサイズを小さくすると、キャッシュ ヒット率が低下する可能性があります。ただし、この場合、キーのエビクションは想定されているため、データの損失を心配する必要はありません。
キーを失いたくない Redis のユースケースでは、データを格納するのに十分な空き容量がある小さなクラスタにのみスケールダウンする必要があります。新しいターゲット シャード数は、データで使用されるメモリの少なくとも 1.5 倍にする必要があります。
つまり、クラスタ内のデータ量の 1.5 倍のシャードをプロビジョニングする必要があります。/cluster/memory/total_used_memory 指標を使用して、
インスタンスに保存されているデータの量を確認できます。
CPU 使用率のベスト プラクティス
予期しないゾーン停止が発生すると、使用できないゾーンのノードから容量が失われるため、クラスタの CPU リソースが減少します。高可用性クラスタを使用することをおすすめします。シャードごとに複数のレプリカを使用すると(シャードごとに 1 つのレプリカではなく)、停止時に追加の CPU リソースが提供されます。シャードごとに最大 5 つのレプリカを使用できます。
また、予期しないゾーン停止が発生した場合に、失われた容量からの追加トラフィックを処理するのに十分な CPU オーバーヘッドをノードに確保できるように、ノードの CPU 使用率を管理することをおすすめします。プライマリとレプリカの CPU 使用率は、
メインスレッド CPU 秒/cluster/cpu/maximum_utilization 指標を使用してモニタリングする必要があります。
ノードごとにプロビジョニングするレプリカの数に応じて、次の /cluster/cpu/maximum_utilization CPU 使用率の目標値をおすすめします。
- ノードごとに 1 つのレプリカがあるインスタンスの場合、プライマリの
/cluster/cpu/maximum_utilization値を 0.5 秒、レプリカの値を 0.5 秒に設定します。 - ノードごとに 2 つ以上のレプリカがあるインスタンスの場合、プライマリの
/cluster/cpu/maximum_utilization値を 0.9 秒、各レプリカの値を 0.5 秒に設定します。
指標の値がこれらの推奨値を超える場合は、インスタンス内のシャード数をスケールアップすることをおすすめします。インスタンスのレプリカ数が 5 つ未満の場合は、レプリカの数を最大 5 つまでスケールアップすることもできます。
リソースを大量に消費する Redis コマンド
リソースを大量に消費する Redis コマンドの使用は避けることを強くおすすめします。これらのコマンドを使用すると、次のようなパフォーマンスの問題が発生する可能性があります。
- レイテンシが高く、クライアントがタイムアウトする
- メモリ使用量を増やすコマンドによるメモリ負荷
- Redis メインスレッドがブロックされるため、ノードのレプリケーションと同期中にデータが失われる
- ヘルスチェック、オブザーバビリティ、レプリケーションが停止する
次の表に、リソースを大量に消費する Redis コマンドの例と、リソース効率の高い代替コマンドを示します。
| カテゴリ | リソースを大量に消費するコマンド | リソース効率の高い代替コマンド |
|---|---|---|
| キースペース全体で実行する | KEYS |
SCAN |
| 可変長の鍵セットに対して実行する | LRANGE |
クエリに使用する範囲のサイズを制限します。 |
ZRANGE |
クエリに使用する範囲のサイズを制限します。 | |
HGETALL |
HSCAN |
|
SMEMBERS |
SSCAN |
|
| スクリプトの実行をブロックする | EVAL |
スクリプトが無限に実行されないようにします。 |
EVALSHA |
スクリプトが無限に実行されないようにします。 | |
| ファイルとリンクを削除する | DEL |
UNLINK |
| パブリッシュとサブスクライブ | PUBLISH |
SPUBLISH |
SUBSCRIBE |
SSUBSCRIBE |
Redis クライアントのベスト プラクティス
アプリケーションは、Memorystore for Redis Cluster インスタンスに接続するときに、クラスタ対応の Redis クライアントを使用する必要があります。クラスタ対応クライアントと サンプル構成の例については、クライアント ライブラリのコードサンプルをご覧ください。クライアントは、正しいノードにリクエストを送信し、クラスタのリダイレクトによるパフォーマンスのオーバーヘッドを回避するために、ハッシュ スロットからクラスタ内の対応するノードへのマッピングを維持する必要があります。
クライアント マッピング
クライアントは、次のような場合に、スロットとマッピングされたノードの完全なリストを取得する必要があります。
クライアントが初期化されるときに、初期スロットからノードへのマッピングを設定する必要があります。
サーバーから
MOVEDリダイレクトを受信した場合。たとえば、以前のプライマリ ノードによって提供されていたすべてのスロットがレプリカによって引き継がれるフェイルオーバーの場合や、スロットがソース プライマリからターゲット プライマリ ノードに移動されるリシャーディングの場合などです。サーバーから
CLUSTERDOWNエラーを受信した場合、または特定のサーバーへの接続が永続的にタイムアウトした場合。サーバーから
READONLYエラーを受信した場合。これは、プライマリがレプリカに降格された場合に発生する可能性があります。また、クライアントはトポロジを定期的に更新して、変更に備えてクライアントをウォームアップし、新しいレプリカノードが追加された場合など、サーバーからのリダイレクトやエラーが発生しない変更について学習する必要があります。トポロジの更新の一環として、古い接続もすべて閉じる必要があります。これにより、コマンドの実行中に失敗した接続を処理する必要性が軽減されます。
クライアントの開拓
通常、クライアントの開拓は、Redis サーバーに CLUSTER SLOT、CLUSTER NODE、CLUSTER SHARDS コマンドを発行して行います。CLUSTER SHARDS コマンドを使用することをおすすめします。CLUSTER SHARDS は、クラスタのより効率的で拡張可能な表現を提供することで、CLUSTER SLOTS コマンド(非推奨)を置き換えます。
クラスタ クライアントの開拓コマンドのレスポンス サイズは、クラスタのサイズとトポロジによって異なります。ノード数が多い大規模なクラスタでは、レスポンスが大きくなります。そのため、クラスタ トポロジの開拓を行うクライアントの数が無制限に増加しないようにすることが重要です。
これらのトポロジの更新は Redis サーバーでコストがかかりますが、アプリケーションの可用性にも重要です。したがって、各クライアントが一度に 1 つの開拓リクエストを行い(結果をメモリにキャッシュに保存)、リクエストを行うクライアントの数を制限して、サーバーの過負荷を回避することが重要です。
たとえば、クライアント アプリケーションが起動したときや、 サーバーとの接続が切断されてクラスタの開拓を行う必要がある場合、よくある間違いは、クライアント アプリケーションが再試行時に 指数バックオフを追加せずに、複数の再接続リクエストと開拓リクエストを行うことです。 これにより、Redis サーバーが長時間応答しなくなり、CPU 使用率が非常に高くなる可能性があります。
Redis での開拓の過負荷を回避する
接続リクエストと開拓リクエストの急増による影響を軽減するには、次のことをおすすめします。
クライアント アプリケーションからの同時受信接続数を制限するために、有限で小さいサイズのクライアント接続プールを実装します。
タイムアウトによりクライアントがサーバーから切断された場合は、ジッター付きの指数バックオフで再試行します。これにより、複数のクライアントが同時にサーバーに過負荷をかけることを回避できます。
Memorystore for Redis Cluster の開拓エンドポイントを使用して、クラスタの開拓を行います。開拓エンドポイントは高可用性であり、クラスタ内のすべてのノード間で負荷分散されます。また、開拓エンドポイントは、クラスタの開拓リクエストを最新のトポロジ ビューを持つノードにルーティングしようとします。
永続性のベスト プラクティス
このセクションでは、永続性のベスト プラクティスについて説明します。
RDB 永続性とレプリカの追加
RDB スナップショットを使用してインスタンスをバックアップする場合や、インスタンスにレプリカを追加する場合に最適な結果を得るには、次のベスト プラクティスを使用します。
メモリ管理
RDB スナップショットは、プロセス フォークと「コピーオンライト」メカニズムを使用して、インスタンスのスナップショットを作成します。 ノードへの書き込みパターンに応じて、書き込みによってアクセスされたページがコピーされるため、ノードの使用済みメモリが増加します。メモリ使用量は、ノード内のデータのサイズの 2 倍になることがあります。
スナップショットを完了するのに十分なメモリがノードにあることを確認するには、
maxmemory をノード容量の 80% に維持または設定して、20% をオーバーヘッド用に予約します。スナップショットのモニタリングに加え、このメモリ オーバーヘッドにより、ワークロードのスナップショットを正常に処理できます。また、レプリカを追加する場合は、書き込みトラフィックをできるだけ減らします。詳細については、書き込み負荷が高いクラスタをモニタリングするをご覧ください。
古いスナップショット
古いスナップショットからノードを復元すると、大量の古くなったキー、またはスキーマの変更などのデータベースに対するその他の変更を調整しようとするため、アプリケーションのパフォーマンスに問題が発生する可能性があります。古いスナップショットからの復元が心配な場合は、RDB 永続性機能を無効にできます。 永続性を再度有効にすると、次のスケジュールされたスナップショット間隔でスナップショットが作成されます。
RDB スナップショットのパフォーマンスへの影響
ワークロード パターンによっては、RDB スナップショットがインスタンスのパフォーマンスに影響し、アプリケーションのレイテンシが増加する可能性があります。スナップショットの頻度が低くても問題ない場合は、インスタンス トラフィックが少ない期間に実行するようにスケジュールすることで、RDB スナップショットのパフォーマンスへの影響を最小限に抑えることができます。
たとえば、インスタンスのトラフィックが午前 1 時から午前 4 時まで少ない場合は、開始時刻を午前 3 時に設定し、間隔を 24 時間に設定します。
システムの負荷が一定で、スナップショットが頻繁に必要な場合は、パフォーマンスへの影響を慎重に評価し、ワークロードに RDB スナップショットを使用するメリットを比較検討してください。
レプリカを追加
レプリカを追加するには、RDB スナップショットが必要です。RDB スナップショットの詳細については、メモリ管理をご覧ください。
シングルゾーン クラスタを使用する場合
レプリカを使用しないようにクラスタを構成する場合は、 シングルゾーン クラスタを使用することをおすすめします。 その理由は次のとおりです。
費用とパフォーマンス
コストを最小限に抑え、同じリージョンに配置されているクライアントのパフォーマンスを最大にすることが主な目的である場合は、シングルゾーン クラスタを選択することをおすすめします。
停止の影響を最小限に抑える
シングルゾーン クラスタを選択すると、ゾーン停止がクラスタに影響する可能性が低くなります。すべてのノードを単一のゾーンに配置することで、ゾーン停止がサーバーに影響する可能性が 100% から 33% に低下します。使用できないゾーンに配置されているノードが影響を受ける可能性は 100% ですが、クラスタが配置されているゾーンがダウンする可能性は 33% です。
迅速なリカバリー
シングルゾーン クラスタでゾーン停止が発生した場合、Memorystore for Redis Cluster はデータの復元を効率化します。機能しているゾーンに新しいクラスタを迅速にプロビジョニングし、アプリケーションをリダイレクトして、オペレーションの中断を最小限に抑えることができます。
Lettuce のベスト プラクティス
このセクションでは、Lettuce を使用して Memorystore for Redis Cluster インスタンスに接続するためのベスト プラクティスについて説明します。
パラメータ値を更新する
Lettuce を使用する場合は、validateClusterNodeMembership パラメータを false に変更します。そうしないと、トポロジが変更されたときに unknownPartition エラーが発生する可能性があります。
Transport Layer Security(TLS)を有効にする
このセクションでは、Transport Layer Security(TLS)を使用するセキュリティ上のメリットとパフォーマンスへの影響について説明し、有効にする際の推奨事項を示します。
セキュリティ上の特典
TLS を使用すると、次のようなセキュリティ上のメリットがあります。
- Identity and Access Management(IAM)認証: TLS はこのタイプの認証を使用して、中間者攻撃などのサーバー スプーフィング攻撃から保護します。
- 転送中の暗号化: Google Cloudの組み込み暗号化により、Google のネットワーク内のトラフィックが インフラストラクチャ レベルで保護されます。ただし、これには Google のホストとネットワーク スタックの両方を信頼する必要があります。この暗号化は透過的でデフォルトで有効になっていますが、エンドツーエンドではありません。一方、TLS はアプリケーション レイヤで転送中の暗号化を使用します。このエンドツーエンドの暗号化により、暗号鍵とプロセスをより詳細に制御できます。
- 認証トークンの保護: IAM 認証を使用している場合、TLS を有効にすると、認証トークンが公開されて漏洩するリスクを最小限に抑えることができます。
パフォーマンスへの影響
TLS は次のようにパフォーマンスに影響します。
接続を確立する: TLS セッションを確立したクライアントとサーバーは、セッションを再開できます クライアントとサーバー間の接続を確立するリソースを大量に消費するプロセスを繰り返すことなく。TLS 再開を有効にすると、クライアントとサーバー間の接続を確立するオーバーヘッドが軽減されます。
TLS 再開を確立しない場合、接続の確立にはリソースを大量に消費します。新規接続と既存の接続の両方で、クライアントとサーバー間の接続数が多いと、接続がタイムアウトする可能性があります。Memorystore for Redis Cluster はタイムアウトした接続を再確立しようとするため、接続の確立に使用するリソースが増加し、雪だるま式に増加する可能性があります。
データの暗号化と復号: データの暗号化と復号には、クライアントとサーバーの両方に影響する CPU 使用率の高いオペレーションが含まれます。これにより、クラスタの容量が減少し、クラスタのレイテンシが増加する可能性があります。
推奨事項
TLS を有効にするかどうかを検討する際は、TLS のメリットとデメリットを考慮しながら、セキュリティ ポリシーを評価することをおすすめします。TLS を有効にする場合は、次の点を考慮してください。
- TLS 再開を有効にすると、接続の確立のオーバーヘッドが軽減されます。クライアントとサーバー間の接続は、最初の接続でのみ必要です。ただし、クライアントのクラスタサイズが急激に拡大すると、新しいクライアント ホストの最初の完全なハンドシェイクが原因で、一時的な中断が発生する可能性があります。
- 一部のクライアント ライブラリでは、TLS を有効にする組み込みの制御が提供されていない場合がありますが、カスタムコードを使用して この機能をクラスタに統合できます。