インタビューはまったく難しくありません:Redisクラスターモード分析、ハッシュスロット、クラスターモードの高可用性、一貫性、クライアントJedisPool、クラスター拡張

1クラスターモードとマスタースレーブモードの違い

  • マスタースレーブモードでは、マスター/スレーブノードにキャッシュされたデータの全量が含まれます(データ量が多い場合に拡張ボトルネックが発生します)
  • クラスタークラスターモードでは、フルキャッシュデータは複数のノードに分散され、各ノードにはフルキャッシュデータの一部のみが含まれます。

2クラスターモードでのノードデータの分割

データはハッシュスロットに従って分割されます。

Redisクラスターには16384個のハッシュスロットがあり、各キーはCRC16とモジュロ16384によってチェックされ、キーがどのスロットに対応するかが決定されます。

たとえば、現在のクラスターには3つのノードがあり、次のようになります。

  1. ノードAには、0〜5500のハッシュスロットが含まれています
  2. ノードBには、ハッシュスロット5501〜11000が含まれています
  3. ノードCには、ハッシュスロット11001〜16384が含まれています

3クラスターモードには、少なくとも3つのマスターノードが必要です

  1. クラスターモードは、クラスターの状態を同期するためのゴシッププロトコルに基づいているため、完全に分散化されたモードです。
  2. したがって、クラスター状態の一貫性を実現するには、「マジョリティ」の原則に従う必要があります(たとえば、ノードが突然接続に失敗し、接続できないと考えるノードの大多数だけが実際にはそうではない)接続済み)
  3. したがって、少なくとも3つのノードが必要です
    1. 分散投票シナリオでは、3ノードクラスターは1ノードのハングポイントを許容できます
    2. Redisの構成cluster-require-full-coverage = no、1つのマスターノードがダウンしている場合でも、他のマスターノードはサービスを提供できます(=はい、1つのマスターノードがダウンしている限り、クラスターは使用できません)

4クラスターモードクラスターの高可用性

ノードの高可用性を確保するために、通常はマスタースレーブモードが採用され、各マスターノードにはスレーブノードがあります。

したがって、クラスターはクラスターモードでの可用性が高く、3つのマスターと3つのスレーブが必要です。

5クラスターモードでのシングルキー操作

5.1単純なクライアントredis-cli操作

redis 127.0.0.1:7000> set foo bar
-> Redirected to slot [12182] located at 127.0.0.1:7002
OK
  • 現在の操作のキーに対応するスロットが、現在のクライアントが接続されているノード上にない場合、クラスターはMOVEDエラーを返し、正しいターゲットノードを示します。
  • その後、クライアントは引き続き正しいターゲットノードにリクエストを送信します

5.1.1操作を正しいノードに転送するために、クライアントがサーバーではなくリダイレ​​クトを実行するのはなぜですか?

推測:

サーバーが操作を正しいノードに転送するのに役立つ場合:

  • サーバーはブロックされ(クライアント要求のシングルスレッド処理のため)、バックグラウンドは操作を他のサーバーに転送し、結果を待ちます
  • プロセス全体には、4つのネットワーク送信が含まれます(クライアントリダイレクト方式と同じ数のネットワーク送信)

クライアントリダイレクトの場合:

  • サーバーは、リダイレクトコマンドを返した後、他のクライアント要求の処理を続行してもブロックしません
  • クライアントリダイレクト、プロセス全体には4つのネットワーク送信が含まれます(サーバー転送操作の数と同じ)

対照的に、クライアントリダイレクトはより手頃な価格です。

5.2 JavaJedisPoolでの操作

シンプルクライアントのredis-cliモードには問題があります。現在のキーに対応するスロットがどのノードであるかを事前に知ることは不可能であるため、多くのリダイレクトが生成されます。

JedisPoolはJavaredis接続プールであり、<slot、node>の対応する関係をキャッシュします。したがって、操作を実行するときは、最初にキーに対応するスロットを計算してから、スロットに対応するノードを見つけます。

6クラスターモードでのマルチキーの操作

複数のキーが複数のスロットに対応する場合があり、複数のスロットが異なるノードに分散されているため、クラスターモードは通常、マルチキー関連の操作をサポートしていません。

// 以 Java Redis 客户端 Jedis 为例:
// 对于 multi keys,要求所有的 key 都对应同一个 slot 才能执行(这个限制更严格,更宽松一点的限制是:可以对应多个 slot,但这些slot 都在一个节点上)
if (keys.length > 1) {
    
    
  int slot = JedisClusterCRC16.getSlot(keys[0]);
  for (int i = 1; i < keyCount; i++) {
    
    
    int nextSlot = JedisClusterCRC16.getSlot(keys[i]); // 计算key对应的 slot
    if (slot != nextSlot) {
    
     // slot 不一致则抛异常
      throw new JedisClusterException("No way to dispatch this command to Redis Cluster "
          + "because keys have different slots.");
    }
  }
}

6.2ハッシュタグを使用して、キーに対応するスロットを制御します

シナリオによっては、1つのノードに複数のキーがあることを期待しています。それを制御するにはどうすればよいですか。

  • redisはキーハッシュタグを提供します
  • {ハッシュタグ}キー値
  • キーにハッシュタグがある場合、特定のキーではなく、CRC16の計算時にハッシュタグが使用されます
  • したがって、複数のキーを同じノード(同じスロット)に配置する場合は、複数のキーに同じハッシュタグを使用させることができます。

7非強力な一貫性

理由:

  1. マスタースレーブ同期。
    1. 非同期で実行されます。書き込みがまだ同期されていない場合でも、マスターがハングし、この時点で書き込みが失われる可能性があります。
  2. ネットワークパーティションのマスタースレーブスイッチング。
    1. ネットワークパーティションはクラスターモードで表示されます。マスターノードとスレーブノードが異なるパーティションにあり、パーティションスレーブノードの1つがマスターとして選択されている場合、元のマスターノードの書き込み操作の一部が行われていない可能性があります。ネットワークパーティションのため、スレーブに同期されます。
假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六个节点。 
其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点。
还有一个客户端 Z1 。

假设集群中发生网络分区,那么集群可能会分为两方,
大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,
小部分的一方则包含节点 B 和客户端 Z1 。
Z1仍然能够向主节点B中写入, 
如果网络分区发生时间较短,那么集群将会继续正常运作,
如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了。

8クラスタークラスターの展開/再シャーディング

ノードの追加、ノードの削除、および再シャーディングは、基本的に1つのタイプの操作です。スロットの移行です。

たとえば、新しいノードが追加された場合、他のノードの一部のスロットが新しいノードに割り当てられます。

クラスタモードでは、データ移行の基本単位はスロットです。

8.1スロットの移行

ここに画像の説明を挿入

スロット移行手順:

  1. スロットを中間遷移状態としてマークします(上の図に示すように、ノードAから移動する場合、Aでマークされたスロットは移行状態であり、ノードBに移動する場合、Bでスロットをマークすることはインポート状態です。 )
  2. スロット内のキーに従って1つずつ移行し、移行を同期的にブロックします
    1. AはスロットのキーをBに送信します
    2. Bデータを受信したら、ローカルに保存して[OK]と返信します
    3. A OKの返信を受け取ったら、ローカルキーを削除します
  3. この移行プロセスが切断された後、回復可能

8.2スロット移行中のクライアントの要求処理

スロット移行プロセスにより、スロット内のキーの一部はノードAにあり、一部はノードBにあるため、クライアントの要求処理は大幅に変更されます。

  1. クライアントは最初にスロットに対応する古いノードにアクセスします
  2. データがまだ古いノードにある場合、古いノードは正常に処理されます
  3. データが古いノードに存在しなくなった場合、古いノードはアスクBリダイレクト順序をクライアントに返します
  4. クライアントは最初にaskBを実行します
  5. 次に、クライアントはget操作を実行します

リダイレクト時にgetを直接使用できないのに、最初にaskコマンドを発行するのはなぜですか?

スロットはノードBに属していない(まだノードAに属している)ため、getコマンドを直接送信すると、BはクライアントをAにリダイレクトし、循環リダイレクトを引き起こします。

おすすめ

転載: blog.csdn.net/hugo_lei/article/details/106390853
おすすめ