Memorystore for Redis Cluster でのゼロ ダウンタイムのスケーリング: 仕組み
Google Cloud Japan Team
※この投稿は米国時間 2023 年 11 月 3 日に、Google Cloud blog に投稿されたものの抄訳です。
フルマネージドでスケーラビリティに優れた低レイテンシの Redis Cluster サービスである Memorystore for Redis Cluster の一般提供に先立ち、「仕組み(Under the Hood)」シリーズのブログでその差別化要因となる機能をご紹介します。オープンソース ソフトウェアに大幅な機能強化を行った AlloyDB のような Google Cloud の他のサービスと同様に、Google は Redis エンジンにも内部的な改善を行いました。このブログは、Redis Cluster の機能強化について説明するシリーズの第 1 回目です。
Redis Cluster を選ぶ理由
Redis が継続的に成長する中で、多くのデベロッパーがスケーラビリティとパフォーマンスの向上を求めて Redis Cluster を使用しています。実際、2015 年に OSS(オープンソース ソフトウェア)の Redis Cluster がリリースされた主な動機は、超低レイテンシでルックアップを提供できる、スケーラビリティに優れたインメモリ データストアの必要性でした。Redis はシングル スレッドであるため、ノードを追加することでスケール「アウト」(または「水平」スケーリング)するクラスタ化されたサービスにより、VM を拡大させることでのみスケール「アップ」する単一の「スタンドアロン」ノードよりもはるかに優れたパフォーマンスを提供します。Redis Cluster はエンジン内に高可用性を直接統合しているため、Sentinel のような外部ツールの必要がなくなりました。さらに、Redis Cluster のアーキテクチャはオペレーションの柔軟性を提供します。アップデートやメンテナンスの際にはクラスタの特定のセグメントのみが影響を受けるため、ユーザーデータへの影響を最小限に抑えながら継続的なサービスを提供できます。
Redis Cluster でパフォーマンスをスケールするという魅力的な機会があるにもかかわらず、信頼性の高い自動化の欠如と Redis Cluster のスケーリング オペレーションのリスクを伴う性質により、現在でもユーザーがそのすべてのメリットを実現できないことが多くあります。このブログでは、OSS スケーリングの欠点に対処するために Memorystore チームが Redis に行った具体的な機能強化について詳しく説明します。これらの機能強化を行うたびに Google は OSS Redis コミュニティと積極的と関わり、設計、コード、改善点を共有してきました。OSS に貢献し、作業を核となる Redis Cluster プロジェクトと一致させることで、互換性を確保し、オープンソースの原則に対するコミットメントを体現し、不一致な行動を回避できます。
スケールインとスケールアウトの両方のオペレーションのリスクを回避するために、Google は Memorystore for Redis Cluster を使用して、Redis エンジンに大幅な機能強化を行いました。真のゼロ ダウンタイムのスケーラビリティにより従量課金制モデルを十分に活用できるため、ピークイベントに備えて容量を増やしたり、イベント後には容量を縮小したりして、必要な分に対してのみ料金を支払うことができます。ブラック フライデーやサイバー マンデーのセール期間中、多くの企業は圧倒的な量のトランザクションとユーザー インタラクションに備えなければなりません。フルマネージド型の Memorystore for Redis Cluster を活用することで、このピークに備えてインフラストラクチャを迅速かつ効率的にスケールし、需要が落ち着いた時点で縮小できるため、費用を最適化しながらシームレスなユーザー エクスペリエンスを実現します。
OSS Redis スケーリングの問題点
以下で、OSS Redis のスケーリングに関連する課題を詳しく説明します。その次のセクションでは、これらのリスクに Google がどのように対処しているかをご紹介します。
理論的には、セルフマネージド Redis Cluster のスケールアウトはごく簡単なものです。Compute Engine のようなサービスで稼働している場合、まず適切なリソースとネットワーク構成で新しい VM のセットをプロビジョニングします。次に、Redis CLI を使用してこれらのノードをクラスタに統合し、一部をプライマリ ノード、その他をレプリカとして指定します。最後に、Redis CLI を使用して新しく統合されたノードにスロットを再分配します。
しかし多くの場合、実際の事態ははるかに複雑です。クラスタのスケーリングは、多くの場合、時間的制約があります。CPU の使用率が高い、またはメモリが少ないというアラートを受け取ったかもしれません。そして手動による操作であることから、エラーが発生しがちです。また、多くのノードやレプリカを持つクラスタを管理する場合、複雑さは増すばかりです。さらに、OSS Redis Cluster の現在の状態では、リシャーディング プロセスは完全には自律していません。Redis の外部で実行される外部エージェントがソースノードから鍵を抽出してターゲット ノードにディスパッチする手順を実行する必要があります。
Redis Cluster は、16,384 のスロットにデータをパーティショニングし、それぞれを特定のノードに割り当てます。リシャーディングを行う主な理由は、ワークロードの変化に合わせてストレージとコンピューティングの容量を再調整するためです。これにより、ノードはデータ責任を管理するために十分な準備ができます。
各スロットには、「安定」、「インポート中」、「移行中」の 3 つの「移行の状態」のうちのいずれかが必要です。それぞれ、リシャーディングのメカニズムにおいて重要な役割を果たします。Redis は、これらの状態をメモリ上に維持します。「安定」状態は、スロットの通常の動作状態を意味します。「インポート中」状態のスロットを持つノードはまだデータ所有者ではなく、ASKING コマンドの接頭辞が付いたリクエストのみに対応します。「移行中」状態のスロットを持つノードは、データ所有権を保持します。クライアントから要求された鍵が指定されたノードに見つからない場合、そのノードは「-ASK」エラーのレスポンスを返し、その鍵を含むターゲット ノードを示します。その後、クライアントはターゲット ノードに「ASKING」コマンドを送信し、スロットの移行中に鍵にアクセスします。この「移行状態」管理の複雑なコレオグラフィにより、大幅なオーバーヘッドが追加されるだけでなく、すべての潜在的な失敗ケースを特定して対処することが難しくなります。特有の複雑さはシステムの予測可能性と信頼性を低下させ、シンプルなエラー回復戦略の設計を困難にし、OSS Redis システムの全体的な堅牢性とパフォーマンスに影響を与えます。
スケーリング オペレーション中に、外部エージェントは CLUSTER SETSLOT コマンドを活用して、発行元ノードと受信ノード両方のスロットの移行状態を操作します。その後、CLUSTER GETKEYSINSLOT を適用して移動する鍵を抽出し、MIGRATE を適用して移行元から移行先へ移動して、各鍵がハッシュ値によってスロットに関連付けられ、そのまま転送されるようにします。
完了すると、ノード間のクラスタの構成が更新され、新しいスロットからノードへの割り当てが反映されます。この同期は、クラスタのアーキテクチャの一貫した正確なビューを維持するために不可欠です。
これを背景に、OSS Redis Cluster のスケーリングでよくある課題をご紹介します。
1. 可用性
空のシャードでの高可用性の喪失
OSS Redis では、空のシャード(割り当てられたスロットがないシャード)は運用上の課題をもたらします。一つは、最初のスロットの移行が完了するまでは ID が確認できないため、高度な状態追跡を行わない限り、外部のエージェントが問題を特定するのが困難だからです。さらに、レプリカが配置されていても、空のシャードは最初のスロットを受け取るまで自動フェイルオーバーをサポートしません。これらのシャードの一つのプライマリ ノードがその最初のスロットのインポート中に応答しなくなった場合、サービスの中断と、そのスロットに関連する潜在的なデータ損失の両方につながる可能性があります。
スロット所有権確定での単一障害点
OSS Redis クラスタの移行状態は、レプリカには反映されません。その結果、自動フェイルオーバー中にスロットの移行状態が失われ、新たに選出されたプライマリが進行中の移行に気づかないままとなる可能性があります。状態の継続性がないため、元のプライマリがクラッシュやメモリ不足(OOM)のイベントを経験した場合、潜在的なデータ損失のリスクが高まります。この問題を解決するには、高度な外部エージェントが必要となり、複雑な状況と運用のオーバーヘッドが生じます。
ワークロードに対する高い影響
現在の OSS 移行プロセスは、Redis サーバーの外部でエージェントによって行われます。エージェントの外部的な性質は、エージェントの可用性と耐久性に関連するリスクをもたらすだけではありません。たとえば、エージェントは移行する安全なキーカウントを決定するために利用可能なメモリを容易にチェックできないため、スケーリング アクティビティのリスクも増大します。エージェントによるデータ量移動の管理は制限されているため、外部エージェントからのスケーリング オペレーションは実行中のユーザー ワークロードでのブロックを長引かせ、クラスタの操作に直接影響を与える可能性があります。エージェントはメモリ負荷とクライアントのワークロード レベルの両方をリアルタイムで可視化できないため、移行オペレーションとお客様の継続的なワークロードのバランスを取ることが困難になります。たとえば、移行が誤って顧客アクティビティの急増と重なり、ユーザーの操作への影響が増幅され、顕著なサービスの中断につながる可能性があります。
2. 信頼性
OOM のリスクの増加
外部を利用する移行は、同時に移行されるデータ量の制御が制限されることに起因する重大な OOM リスクをもたらします。大規模な鍵や実装済みのハッシュマップのような密度の高いデータ構造の移行を処理する場合、ソースノードは突然強度なメモリの負荷を経験する可能性があります。外部エージェントにとって明らかな課題は、このメモリ負荷に対するリアルタイムの可視性がないことです。メモリ不足の状態は、進行中の移行プロセスを危険にさらすだけでなく、Redis プロセスの OOM の強制終了にもつながり、アプリケーション自体が中断する可能性があります。
一時的なエラーに対する復元力が低い
移行プロセスでは、ネットワークの問題やノードのフェイルオーバーなどの問題による中断の影響を受けやすくなります。そのような場合、外部エージェントは移行コマンドから最小限のエラー フィードバックを取得します。根本原因を判断するために、エージェントは影響を受けたノード上で Redis コマンドを実行し、お客様のワークロードを管理している間にも負荷を加えます。取得した情報はすぐに古くなります。さらに、中断された移行を再開するには、エージェントから明示的な操作が要求されます。このような手間のかかる介入は面倒なだけでなく、エラーのリスクも高くなります。
3. 効率性
移行オーバーヘッドが高くなる
既存の OSS スロット移行プロセスでは、Redis と外部エージェント間で複数のプロセス間通信(IPC)が発生します。このプロセスでは、エージェントがソースからデータを引き出し、それをターゲットにリレーする必要があるため、ネットワークの帯域幅利用が実質的に 2 倍になります。さらに、この方法は CPU のオーバーヘッドを増加させます。エージェントに読み込まれたデータは、処理されてからターゲットにディスパッチされるため、エージェントとソースの両方で冗長なコンピューティング作業が発生します。これはリソースを圧迫するだけでなく、移行プロセス全体を遅らせ、パフォーマンスに影響を与える可能性があります。
4. 管理
外部への依存
スロット移行プロトコルの外部実行(詳細は Redis の公式ドキュメントに記載)は、移行の開始、監視、終了のための高度な外部エージェントが必要です。このエージェントは、移行を開始してその進行を監督するだけでなく、効果的に複雑なステートマシンになります。このマシン内の各ステップや状態は、データ移行を進めるだけでなく、状態の一貫性を確保するためのエラー処理も考慮する必要があります。多くのステップがあり、それぞれに潜在的な障害モードがあることを考えると、各フェーズの微妙な差異を見極めながらこの一貫した状態を維持することは、運用上の複雑さとリスクを増大させることにつながります。
安定したシャードの特定ができない
OSS Redis 7.0 では CLUSTER SHARDS コマンドが導入されましたが、各シャードを常に安定して特定する仕組みがまだ欠けています。この欠如はオペレーションを複雑にし、特に時間の経過とともにスロットの所有者が変わる場合に、特定のシャードの正確な参照やノードとシャードの関係を理解する妨げとなります。
Memorystore for Redis Cluster が提供するソリューション
このような複雑さとそれに伴うリスクに対処するため、Memorystore for Redis Cluster のユーザーは、ワンクリックまたは API からゼロ ダウンタイムのスケーリング(インまたはアウト)が可能になります。さらに、Memorystore for Redis Cluster の以下の 4 つの改善により、従来の OSS Redis リシャーディングに内在する課題に体系的に対処し、効率性、信頼性、運用の簡素化を強化したプラットフォームを提供します。
- エンジンを使用するスロット移行(#1、#2、#3、#4 の課題に対処)
移行プロトコルを Redis エンジンに移動することで、Memorystore for Redis Cluster はスロット移行を合理化し、スケーリング オペレーションの全体的な複雑さを軽減して、クラスタの可用性と耐久性を向上させます。エンジンのメインスレッドを利用することで、Redis は移行を直接管理し、外部エージェントへの依存を排除します。このアプローチでは、データがソースからターゲットに直接転送されるため、ネットワークと CPU のオーバーヘッドが削減されます。さらに、このシステムの設計は本質的にお客様のワークロードと移行のワークロードのバランスを取り、サーバーのアクティビティに基づいて移行のペースを調整します。中断が発生しても、アーキテクチャはフェイルオーバー後に自動的に移行を再開します。この設計により、Memorystore for Redis Cluster に効率性と復元性に優れた移行メカニズムが提供されます。
- シャード ID の導入(#4 の課題に対処)
Memorystore for Redis Cluster は、シャードの直接参照を可能にするシャード ID を導入しました。これにより、特にノードがダウンしている場合やスロットを所有していない場合に、2 つのノードが同じシャードに属しているかどうかを効率的に検証できます。大きなスロット範囲に依存する必要がなくなることで、システムはより堅牢で操作しやすくなります。この機能は Google が OSS に提供し、OSS Redis 7.2 に追加されました。
- 空のシャードでの自動フェイルオーバー(#1 の課題に対処)
主要機能としてのシャードのコンセプトに基づき、Memorystore for Redis Cluster は Redis エンジンを強化し、空のシャードのリーダー選出を開始します。これにより、プライマリ ノードが失敗しても、レプリカ上に移行された鍵に引き続きアクセスできます。このメカニズムにより、特にスケーリング移行期の信頼性が高まります。
- スケーリングにおける単一障害点の軽減(#1 の課題に対処)
Memorystore for Redis Cluster は、次の 2 つの主要ソリューションを導入しました。
スケーリングを簡素化
Memorystore for Redis Cluster を使用することで、マイクロ秒単位のレイテンシも提供するスケーラブルな Redis Cluster の真の可能性を引き出すことができます。Cloud コンソールにアクセスしてクラスタを作成し、数回のクリックでスケールインまたはスケールアウトを行うことで、今すぐ簡単に始められます。Memorystore for Redis Cluster への移行の詳細については、こちらの移行の詳細な手順に関するブログをご覧ください。この解説シリーズの次回のブログをお楽しみに。ご意見やご感想がございましたら、cloud-memorystore-pm@google.com までお知らせください。
-ソフトウェア エンジニア Ping Xie
-プロダクト マネージャー Kyle Meggs