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 リソースが減少します。高可用性クラスタを使用することをおすすめします。シャードごとに複数のレプリカを使用すると(シャードごとに 1 つのレプリカを使用する場合とは異なり)、停止中に追加の CPU リソースが提供されます。シャードごとに最大 5 個のレプリカを使用できます。

また、予期しないゾーンの停止が発生した場合に、失われた容量からの追加トラフィックを処理するのに十分な CPU オーバーヘッドがノードに確保されるように、ノードの CPU 使用率を管理することをおすすめします。メインスレッド CPU 秒 /cluster/cpu/maximum_utilization 指標を使用して、プライマリとレプリカの CPU 使用率をモニタリングする必要があります。

ノードごとにプロビジョニングするレプリカの数に応じて、次の /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 個までスケールアップすることもできます。

クラスタの CPU 使用率が高い場合や、クラスタのリソースが枯渇している場合(接続数が多すぎる場合など)、クラスタが誤動作し、外部指標が欠落することがあります。

リソースを大量に消費する Redis コマンド

リソースを大量に消費する Redis コマンドは使用しないことを強くおすすめします。これらのコマンドを使用すると、次のようなパフォーマンスの問題が発生する可能性があります。

  • 高レイテンシとクライアント タイムアウト
  • メモリ使用量を増加させるコマンドが原因のメモリ不足
  • Redis メインスレッドがブロックされているため、ノードのレプリケーションと同期中にデータが失われる
  • ヘルスチェック、オブザーバビリティ、レプリケーションの枯渇

次の表に、リソースを大量に消費する Redis コマンドの例と、リソース効率の高い代替コマンドを示します。

カテゴリ リソースを大量に消費するコマンド リソース効率の高い代替手段
キースペース全体に対して実行する KEYS SCAN
可変長鍵セットに対して実行する LRANGE クエリに使用する範囲のサイズを制限します。
ZRANGE クエリに使用する範囲のサイズを制限します。
HGETALL HSCAN
SMEMBERS SSCAN
スクリプトの実行をブロックする EVAL スクリプトが無期限に実行されないようにします。
EVALSHA スクリプトが無期限に実行されないようにします。
ファイルとリンクを削除する DEL UNLINK
パブリッシュとサブスクライブ PUBLISH SPUBLISH
SUBSCRIBE SSUBSCRIBE

スケーリングしきい値のベスト プラクティス

スケーリングしきい値のシナリオは、次のカテゴリに分類されます。

  • メモリ使用率のスケーリング
  • CPU 使用率に基づくスケーリング
  • ホットスポットを軽減するためのスケーリング

ワークロードがキーの強制排除に依存している場合、CPU 使用率またはメモリ使用率のスケールインはおすすめしません。これらのワークロードでは、メモリ使用量が最大容量に達してから、エビクションが自動的に発生することがよくあります。その結果、メモリの急増によりスケールイン オペレーションがブロックされます。

以降のセクションでは、スケーリングが必要となる一般的なシナリオと指標のしきい値について詳しく説明します。

メモリ使用率のスケーリング

メモリ使用量に基づいてスケーリングするタイミングを判断するには、/cluster/memory/average_utilization 指標と /cluster/memory/maximum_utilization 指標をモニタリングします。これらの指標の詳細については、サポートされているモニタリング指標をご覧ください。

クラスタが次のいずれかの条件を満たしている場合は、スケールアウト オペレーションのトリガーを検討してください。

  • クラスタの平均メモリ使用率が、推奨されるしきい値の 70% を超えています。
  • 最大メモリ使用率が 80% を超え、平均メモリ使用率が 50% を超えている。

クラスタが次のいずれかの条件を満たしている場合は、スケールイン オペレーションのトリガーを検討してください。

  • クラスタの平均メモリ使用率が、推奨されるしきい値の 50% を下回った。
  • 最大メモリ使用率が 60% を下回り、平均メモリ使用率が 40% を下回る。

CPU 使用率に基づくスケーリング

CPU 使用率に基づいてスケーリングするタイミングを判断するには、/cluster/cpu/average_utilization 指標と /cluster/cpu/maximum_utilization 指標をモニタリングします。

クラスタが次のいずれかの条件を満たしている場合は、スケールアウト オペレーションのトリガーを検討してください。

  • クラスタの平均 CPU 使用率が、推奨されるしきい値の 70% を超えています。
  • 最大 CPU 使用率が 80% を超え、平均 CPU 使用率が 50% を超えている。

クラスタが次のいずれかの条件を満たしている場合は、スケールイン オペレーションのトリガーを検討してください。

  • クラスタの平均 CPU 使用率が、推奨されるしきい値の 50% を下回った。
  • 最大 CPU 使用率が 60% を下回り、平均 CPU 使用率が 40% を下回った。

ホットスポットを軽減するためのスケーリング

Memorystore for Redis Cluster には、同じ指標の平均と最大のバリエーションが用意されています。これらを使用して、その指標ファミリーのホットスポットを特定できます。最大値は最も負荷の高いクラスタノードを表し、平均値はクラスタ全体の負荷を表します。最大値が平均値よりも大幅に高い場合は、特定のノードが不均衡に読み込まれている(ホットスポット)ことを示します。この問題を解決するには、クラスタをスケールアウトすることをおすすめします。詳細については、クラスタ容量をスケーリングするをご覧ください。

平均と最大値の間に大きな差異がある場合は、クラスタノードに対して INFO memory コマンドと INFO cpu コマンドを実行して、クラスタから直接リアルタイム データを収集できます。これらのコマンドの使用方法については、Redis ドキュメントの INFO をご覧ください。

Redis クライアントのベスト プラクティス

アプリケーションは、クラスタに接続するときにクラスタ対応の 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 のディスカバリ エンドポイントを使用して、クラスタ ディスカバリを実行します。検出エンドポイントは高可用性であり、クラスタ内のすべてのノードでロード バランシングされます。さらに、検出エンドポイントは、最新のトポロジビューを持つノードにクラスタ検出リクエストをルーティングしようとします。

応答しない接続を検出して処理する

Memorystore for Redis Cluster への応答しない接続を検出するようにクライアント アプリケーションを構成することを強くおすすめします。応答しない接続が検出された場合、クライアントは接続をリセットする必要があります。復元力のあるアプリケーションを構築するには、次のクライアント構成をおすすめします。

  • TCP keep-alive パラメータを構成する: TCP keepalive time、TCP keepalive interval、TCP keepalive probes パラメータを設定して、接続がアイドル状態の場合でも、クライアントが応答しない接続をプロアクティブに検出して切断するようにします。たとえば、TCP keepalive time パラメータを 30 秒、TCP keepalive interval を 10 秒、TCP keepalive probes を 3 に設定すると、クライアントは応答しないアイドル状態の接続を 1 分以内にリセットします。
  • TCP ユーザー タイムアウトを構成する: このタイムアウトをクライアントに設定して、未処理のリクエストがあり、応答を停止した接続をリセットします。たとえば、タイムアウトを 15 秒に設定すると、クライアントは 15 秒後に未処理のリクエストがある応答しない接続をリセットします。

永続性のベスト プラクティス

このセクションでは、永続性に関するベスト プラクティスについて説明します。

RDB 永続性とレプリカの追加

RDB スナップショットを使用してクラスタをバックアップする場合、またはクラスタにレプリカを追加する場合、最適な結果を得るには、次のベスト プラクティスを使用します。

メモリ管理

RDB スナップショットは、プロセス フォークと「コピーオンライト」メカニズムを使用して、ノードデータのスナップショットを作成します。ノードへの書き込みパターンに応じて、書き込みによってアクセスされたページがコピーされると、ノードの使用メモリが増加します。メモリ使用量は、ノード内のデータの最大 2 倍になる可能性があります。

ノードにスナップショットを完了するのに十分なメモリがあることを確認するには、maxmemory をノード容量の 80% に維持または設定して、20% がオーバーヘッド用に予約されるようにします。スナップショットのモニタリングに加え、このメモリ オーバーヘッドにより、ワークロードのスナップショットを正常に処理できます。また、レプリカを追加するときは、書き込みトラフィックをできるだけ減らしてください。詳細については、書き込み負荷の高いクラスタをモニタリングするをご覧ください。

古いスナップショット

古いスナップショットからノードを復元すると、大量の古くなったキー、またはスキーマの変更などのデータベースに対するその他の変更を調整しようとするため、アプリケーションのパフォーマンスに問題が発生する可能性があります。古いスナップショットからの復元が懸念される場合は、RDB 永続性機能を無効にできます。永続性を再度有効にすると、次のスケジュールされたスナップショット間隔でスナップショットが作成されます。

RDB スナップショットのパフォーマンスへの影響

ワークロード パターンによっては、RDB スナップショットがクラスタのパフォーマンスに影響し、アプリケーションのレイテンシが増加する可能性があります。スナップショットの頻度を低くしても問題がない場合は、クラスタのトラフィックが少ない期間に実行するようにスケジュールすることで、RDB スナップショットのパフォーマンスへの影響を最小限に抑えることができます。

たとえば、クラスタのトラフィックが午前 1 時から午前 4 時まで少ない場合は、開始時刻を午前 3 時に設定し、間隔を 24 時間に設定します。

システムの負荷が一定で、スナップショットが頻繁に必要な場合は、パフォーマンスへの影響を慎重に評価し、ワークロードに RDB スナップショットを使用するメリットを比較検討してください。

レプリカを追加する

レプリカを追加するには、RDB スナップショットが必要です。RDB スナップショットの詳細については、メモリ管理をご覧ください。

シングルゾーン クラスタを使用するケース

レプリカを使用しないようにクラスタを構成する場合は、シングルゾーン クラスタを使用することをおすすめします。その理由は次のとおりです。

費用とパフォーマンス

費用を最小限に抑え、同じリージョンにあるクライアントのパフォーマンスを最大にすることが主な目的である場合は、シングルゾーン クラスタを選択することをおすすめします。

サービス停止の影響を最小限に抑える

シングルゾーン クラスタを選択すると、ゾーンの停止がクラスタに影響する可能性が低くなります。すべてのノードを単一のゾーンに配置すると、ゾーンの停止がサーバーに影響する可能性が 100% から 33% に低下します。クラスタが配置されているゾーンがダウンする確率は 33% です。これに対して、利用できないゾーンに配置されているノードが影響を受ける確率は 100% です。

迅速な回復

シングルゾーン クラスタでゾーンが停止した場合、Memorystore for Redis Cluster はデータの復元を効率化します。機能しているゾーンに新しいクラスタを迅速にプロビジョニングし、アプリケーションをリダイレクトして、オペレーションの中断を最小限に抑えることができます。

キャパシティ プランニングのベスト プラクティス

リソースを正常にプロビジョニングし、復元力のあるアーキテクチャを構築できるように、次のキャパシティ プランニングのベスト プラクティスをおすすめします。

  • 複数のロケーションにデプロイする: 一時的なリソースの制約により、優先ゾーンにクラスタを作成できない場合は、同じリージョン内の別のゾーンまたは別のリージョンにクラスタを作成してみてください。
  • クロスリージョン アクセスを使用する: 異なるリージョンにあるクラスタにアクセスするようにクライアントを構成します。ローカル リソースの制約により、別のリージョンにあるクラスタをプロビジョニングする必要がある場合は、クライアントがクラスタに接続できます。
  • クロスリージョン レプリケーションを使用する: 障害復旧のために、代替リージョンのセカンダリ クラスタをプライマリ読み取りまたは書き込みクラスタにプロモートするには、スイッチオーバーを実行します。

レタスのベスト プラクティス

このセクションでは、Lettuce を使用してクラスタに接続するためのベスト プラクティスについて説明します。

パラメータ値を更新する

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 を有効にする組み込みコントロールが用意されていない場合がありますが、カスタムコードを使用してこの機能をクラスタに統合できます。