このページは、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 秒 /cluster/cpu/maximum_utilization
指標を使用して、プライマリとレプリカの CPU 使用率をモニタリングする必要があります。
ノードごとにプロビジョニングするレプリカの数に応じて、次の /cluster/cpu/maximum_utilization
CPU 使用率の目標値をおすすめします。
- ノードごとに 1 つのレプリカがあるインスタンスの場合は、プライマリの
/cluster/cpu/maximum_utilization
値を 0.5 秒、レプリカの/cluster/cpu/maximum_utilization
値を 0.5 秒に設定します。 - ノードあたり 2 つ以上のレプリカがあるインスタンスでは、プライマリの
/cluster/cpu/maximum_utilization
値を 0.9 秒、各レプリカの/cluster/cpu/maximum_utilization
値を 0.5 秒に設定します。
指標の値がこれらの推奨事項を超える場合は、インスタンスのシャード数をスケールアップすることをおすすめします。インスタンスのレプリカが 5 つ未満の場合は、レプリカの数を最大 5 つまでスケールアップすることもできます。
リソースを大量に消費する Redis コマンド
リソースを大量に消費する Redis コマンドは使用しないことを強くおすすめします。これらのコマンドを使用すると、次のパフォーマンスの問題が発生する可能性があります。
- レイテンシが高く、クライアントがタイムアウトする
- メモリ使用量を増やすコマンドによるメモリ負荷
- Redis メインスレッドがブロックされるため、ノードのレプリケーションと同期中にデータ損失が発生する
- ヘルスチェック、オブザーバビリティ、レプリケーションの不足
次の表に、リソースを大量に消費する Redis コマンドの例と、リソース効率の高い代替コマンドを示します。
カテゴリ | リソースを大量に消費するコマンド | リソース効率の高い代替手段 |
---|---|---|
キースペース全体で実行する | KEYS |
SCAN |
可変長キーセットで実行する | LRANGE |
クエリに使用する範囲のサイズを制限します。 |
ZRANGE |
クエリに使用する範囲のサイズを制限します。 | |
HGETALL |
HSCAN |
|
SMEMBERS |
SSCAN |
|
スクリプトの実行をブロックする | EVAL |
スクリプトが無限に実行されないようにします。 |
EVALSHA |
スクリプトが無限に実行されないようにします。 | |
ファイルとリンクを削除する | DELETE |
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% に低下します。これは、インスタンスが配置されているゾーンがダウンする可能性が 33% であるのに対し、使用できないゾーンにあるノードが影響を受ける可能性は 100% であるためです。
迅速な回復
ゾーンの停止が発生した場合、復旧が効率化されます。機能しているゾーンに新しいインスタンスを迅速にプロビジョニングし、アプリケーションをリダイレクトすることで、オペレーションの中断を最小限に抑えながら対応できます。
Lettuce のベスト プラクティス
このセクションでは、Lettuce を使用して Memorystore for Redis Cluster インスタンスに接続するためのベスト プラクティスについて説明します。
パラメータ値を更新する
Lettuce を使用する場合は、validateClusterNodeMembership
パラメータを false
に変更します。そうしないと、トポロジが変更されたときに unknownPartition
エラーが発生する可能性があります。
Transport Layer Security(TLS)を有効にする
このセクションでは、Transport Layer Security(TLS)を使用するセキュリティ上のメリットとパフォーマンスへの影響について説明し、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 を有効にする組み込みコントロールがない場合がありますが、カスタムコードを使用してこの機能をクラスタに統合できます。