Memorystore for Redis Cluster のベスト プラクティス

このページは、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 リソースが減少します。高可用性クラスタの使用をおすすめします。シャードごとに 2 つのレプリカを使用すると(シャードごとに 1 つのレプリカを使用するのではなく)、停止中に追加の 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 つのレプリカがあるインスタンスの場合は、プライマリで 0.8 秒、各レプリカで 0.5 秒の /cluster/cpu/maximum_utilization 値を目標にします。

指標の値がこれらの推奨事項を超える場合は、インスタンスのシャードまたはレプリカの数をスケールアップすることをおすすめします。

リソースを大量に消費する 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 SLOTCLUSTER 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 を使用して Memorystore for Redis Cluster インスタンスに接続するためのベスト プラクティスについて説明します。

パラメータ値を更新する

Lettuce を使用する場合は、validateClusterNodeMembership パラメータを false に変更します。そうしないと、トポロジが変更されたときに unknownPartition エラーが発生する可能性があります。