Redis Clusterの理解:クライアントが正しいシャードにアクセスする方法
James Reed
Infrastructure Engineer · Leapcell

背景:なぜRedis Clusterが必要なのか
Sentinelモードは、マスター・スレーブモデルに基づいており、読み書き分離を可能にします。また、自動フェイルオーバーをサポートし、システムの可用性を向上させます。ただし、各ノードが同じデータを格納するため、メモリを浪費し、オンラインスケーリングが難しくなります。
その結果、Redis Cluster(シャーディングされたクラスタを実装するためのソリューション)が生まれました。Redis 3.0で導入され、Redisでの分散ストレージを可能にします。データをシャーディングするため、各Redisノードは異なるコンテンツを格納し、オンライン拡張の問題を解決します。さらに、さまざまなRedisインスタンスに分散することで大量のデータを保持でき、レプリケーションとフェイルオーバー機能も提供します。
たとえば、単一のRedisインスタンスが15GB以上のデータを格納する場合、応答時間が遅くなります。これは、RedisのRDB永続化メカニズムが原因です。Redisは、RDB永続化を実行するために子プロセスをフォークし、フォーク操作にかかる時間はRedisデータのサイズに比例します。
この時点で、当然のことながら、15GBのデータを複数のノードに分散して格納すればよいのではないか、と考えるかもしれません。それこそが、Redisシャーディングされたクラスタの背後にある動機です。では、シャーディングされたクラスタとは一体何なのでしょうか?例を見てみましょう。Redisを使用して15GBのデータを格納する場合、単一のRedisインスタンスを使用するか、3つのRedisインスタンスを持つシャーディングされたクラスタを作成できます。次に比較を示します。
シャーディングされたクラスタとRedis Clusterの違い:Redis Clusterは、Redis 3.0で導入された公式のシャーディングされたクラスタ実装です。
さて、データは異なるRedisインスタンスに分散されているため、クライアントは目的のデータがどのインスタンスにあるかを知るにはどうすればよいでしょうか?Redis Clusterがこれをどのように処理するかを見てみましょう。
クライアントはどのシャードにアクセスするかをどのように知るのか?
Redis Clusterは、ハッシュスロットを使用して、データとインスタンス間のマッピングを管理します。
シャーディングされたクラスタは、16,384個のスロットに分割されます。Redisに入る各キーと値のペアは、キーに基づいてハッシュされ、これらの16,384個のスロットのいずれかに割り当てられます。ハッシュ方法は簡単です。CRC16アルゴリズムは16ビットの値を計算し、それを16,384で割った余りを使用します。データベース内のすべてのキーはこれらの16,384個のスロットの1つに属し、クラスタ内のすべてのノードはそれらの一部を処理します。
クラスタ内の各ノードは、ハッシュスロットの一部を担当します。クラスタに3つのノード(A、B、C)があるとします。次に、各ノードは約16,384/3個のスロットを担当します。可能な分布は次のようになります。
- ノードAはハッシュスロット0〜5460を処理します
- ノードBはハッシュスロット5461〜10922を処理します
- ノードCはハッシュスロット10923〜16383を処理します
では、クライアントが対応するデータを持たないRedisインスタンスに読み取り/書き込み操作を送信するとどうなるでしょうか?MOVEDおよびASKリダイレクトの出番です。
3.データがターゲットインスタンスにない場合はどうなるか?
Redis Clusterモードでは、ノードは次のようにリクエストを処理します。
- ハッシュスロットマッピングを使用して、リクエストされたRedisキーが現在のノードに属しているかどうかを確認します。
- ハッシュスロットがこのノードによって管理されていない場合、MOVEDリダイレクトを返します。
- ハッシュスロットが実際にこのノードによって管理され、キーがスロットに存在する場合、対応する結果を返します。
- Redisキーがスロットに存在しない場合、ハッシュスロットが現在移行中(MIGRATING)であるかどうかを確認します。
- Redisキーが移行中の場合、ASKエラーを返し、クライアントをキーの移動先の宛先サーバーにリダイレクトします。
- ハッシュスロットが移行中でない場合は、スロットがインポートされているかどうかを確認します。
- スロットがインポート中で、ASKINGフラグがある場合、操作は直接続行されます。それ以外の場合は、MOVEDリダイレクトが返されます。
3.1 MOVEDリダイレクト
クライアントがRedisインスタンスに読み取り/書き込み操作を送信し、計算されたスロットがそのノードに属していない場合、RedisはMOVEDリダイレクトエラーを返します。この応答には、スロットが存在する正しいRedisノードのIPとポートが含まれています。これが、Redis Clusterで使用されるMOVEDリダイレクトメカニズムです。
3.2 ASKリダイレクト
ASKリダイレクトは、通常、クラスタのリシャーディング中に発生します。リシャーディングにより、スロットが移行します。クライアントがソースノードにアクセスしようとすると、データがすでにターゲットノードに移動している可能性があります。ASKリダイレクトは、移行プロセス中にクライアントを新しいノードに誘導することで、このシナリオの処理に役立ちます。
4.ノードは互いにどのように通信するのか?
Redisクラスタは、複数のノードで構成されています。ノードはどのように通信を行うのでしょうか?それは、ゴシッププロトコルを通じて行われます。ゴシップとは、メッセージ伝播プロトコルであり、各ノードはノードリストから_k_個のノードを定期的に選択し、すべてのノードが合意に達するまで自身が保持する情報を拡散します。これはアルゴリズムの収束と呼ばれます。
ゴシッププロトコルの基本的な考え方: ノードは、ネットワーク内の他のノードと何らかの情報を共有したいと考えています。ノードは、いくつかのノードを定期的かつランダムに選択し、それらのノードに情報を送信します。次に、それらのノードは同じことを行い、情報を他のランダムに選択されたノードに伝播します。通常、情報は1つだけでなく_N_個のノードに伝播されます。この_N_は、_ファンアウト_と呼ばれます。
Redis Clusterは、ゴシッププロトコルを使用して、ノード間で情報を交換します。これには、ノードの障害、新しいノードの追加、マスタースレーブの変更、スロットの割り当てなどに関するデータが含まれます。ゴシッププロトコルには、ping
、pong
、meet
、fail
など、いくつかのタイプのメッセージが含まれます。
- meetメッセージ: 新しいノードに参加を通知します。送信者は、受信者に現在のクラスタへの参加を通知します。
meet
メッセージが正常に受信されると、受信ノードはクラスタに参加し、定期的なping
およびpong
の交換を開始します。 - pingメッセージ: 各ノードは、クラスタ内の他のノードに1秒ごとに
ping
メッセージを送信します。メッセージには、アドレス、スロット、ステータス、最後の通信時間など、2つの既知のノードに関する情報が含まれています。 - pongメッセージ:
ping
またはmeet
メッセージへの応答として送信され、通信が成功したことを確認します。また、2つの既知のノードに関する情報も含まれています。 - failメッセージ: ノードがクラスタ内の別のノードがオフラインであると判断した場合、クラスタ全体に
fail
メッセージをブロードキャストします。このメッセージを受信すると、他のノードは対応するノードをオフラインとしてマークします。
特に、各ノードはクラスタバスを通じて他のノードと通信します。この通信では、特別なポートを使用します。これは、通常のRedisポートに10,000を加えたものです。たとえば、ノードのサービスポートが
6379
の場合、クラスタ通信ポートは16379
になります。ノードは、通信に特別なバイナリプロトコルを使用します。
5.クラスタ内でノードが故障した場合はどうなるか?
Redis Clusterは、高可用性をサポートしています。クラスタ内のノードが故障した場合、システムはフェイルオーバーを使用して、クラスタが外部サービスを適切に提供し続けるようにします。
ノードのオフライン
Redis Clusterは、障害検出にping
/pong
メッセージを使用します。これには、主観的および客観的なオフラインステータスが含まれます。
- 主観的なオフライン(pfail): あるノードが別のノードに到達できないと判断し、オフラインとしてマークします。ただし、これは決定的な障害の判断ではありません。これは1つのノードの視点を反映しているに過ぎず、不正確な場合があります。
- 客観的なオフライン(fail): クラスタ内の_複数のノード_が到達できないことに同意した場合、ノードが真にオフラインであるとマークします。これは、合意に基づいた決定です。オフラインノードがハッシュスロットを所有するマスターの場合、それを置き換えるためにフェイルオーバープロセスがトリガーされます。
たとえば、ノードAがノードBを主観的にオフラインとしてマークした場合、ノードBのステータス情報を他のノードに送信します。ノードCがこのメッセージを受信して解析し、ノードBが
pfail
としてマークされていることを確認した場合、客観的なオフラインプロセスをトリガーします。
- オフラインノードがマスターの場合、Redis Clusterは、スロットを所有するすべてのマスター間で投票プロセスを開始します。半数以上がオフラインとして報告した場合、正式に客観的にオフラインとしてマークされます。
フェイルオーバー回復
障害が検出されると、オフラインノードがマスターの場合、高可用性を維持するために、レプリカ(スレーブ)を選出して置き換える必要があります。フェイルオーバープロセスには、次の手順が含まれます。
- 適格性チェック: レプリカが、故障したマスターを置き換えるための条件を満たしているかどうかを判断します。
- フェイルオーバー遅延準備: レプリカが適格な場合、フェイルオーバーを開始する前に遅延時間を設定します。
- 選挙の開始: フェイルオーバー遅延が終了すると、レプリカは選挙プロセスを開始します。
- 投票収集: ハッシュスロットを保持するマスターのみが投票を許可されます。候補レプリカは、マスターの置き換えを続行するために、十分な票(半分以上)を収集する必要があります。
私たちはLeapcellです。バックエンドプロジェクトのホスティングに最適です。
Leapcellは、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです。
多言語サポート
- Node.js、Python、Go、またはRustで開発します。
無制限のプロジェクトを無料でデプロイ
- 使用量に対してのみ支払い - リクエストも料金もありません。
圧倒的なコスト効率
- アイドル料金なしの従量課金制。
- 例:25ドルで、平均応答時間60ミリ秒で694万件のリクエストをサポートします。
合理化された開発者エクスペリエンス
- 簡単なセットアップのための直感的なUI。
- 完全に自動化されたCI/CDパイプラインとGitOps統合。
- 実用的な洞察を得るための、リアルタイムのメトリクスとロギング。
容易なスケーラビリティと高パフォーマンス
- 高い同時実行性を容易に処理するための自動スケーリング。
- 運用上のオーバーヘッドはゼロ - 構築に集中するだけです。
詳細については、ドキュメントをご覧ください。
Xでフォローしてください:@LeapcellHQ