記事ディレクトリ
1クラスターモードとマスタースレーブモードの違い
- マスタースレーブモードでは、マスター/スレーブノードにキャッシュされたデータの全量が含まれます(データ量が多い場合に拡張ボトルネックが発生します)
- クラスタークラスターモードでは、フルキャッシュデータは複数のノードに分散され、各ノードにはフルキャッシュデータの一部のみが含まれます。
2クラスターモードでのノードデータの分割
データはハッシュスロットに従って分割されます。
Redisクラスターには16384個のハッシュスロットがあり、各キーはCRC16とモジュロ16384によってチェックされ、キーがどのスロットに対応するかが決定されます。
たとえば、現在のクラスターには3つのノードがあり、次のようになります。
- ノードAには、0〜5500のハッシュスロットが含まれています
- ノードBには、ハッシュスロット5501〜11000が含まれています
- ノードCには、ハッシュスロット11001〜16384が含まれています
3クラスターモードには、少なくとも3つのマスターノードが必要です
- クラスターモードは、クラスターの状態を同期するためのゴシッププロトコルに基づいているため、完全に分散化されたモードです。
- したがって、クラスター状態の一貫性を実現するには、「マジョリティ」の原則に従う必要があります(たとえば、ノードが突然接続に失敗し、接続できないと考えるノードの大多数だけが実際にはそうではない)接続済み)
- したがって、少なくとも3つのノードが必要です
- 分散投票シナリオでは、3ノードクラスターは1ノードのハングポイントを許容できます
- 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つがマスターとして選択されている場合、元のマスターノードの書き込み操作の一部が行われていない可能性があります。ネットワークパーティションのため、スレーブに同期されます。
假设集群包含 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スロットの移行
スロット移行手順:
- スロットを中間遷移状態としてマークします(上の図に示すように、ノードAから移動する場合、Aでマークされたスロットは移行状態であり、ノードBに移動する場合、Bでスロットをマークすることはインポート状態です。 )
- スロット内のキーに従って1つずつ移行し、移行を同期的にブロックします
- AはスロットのキーをBに送信します
- Bデータを受信したら、ローカルに保存して[OK]と返信します
- A OKの返信を受け取ったら、ローカルキーを削除します
- この移行プロセスが切断された後、回復可能
8.2スロット移行中のクライアントの要求処理
スロット移行プロセスにより、スロット内のキーの一部はノードAにあり、一部はノードBにあるため、クライアントの要求処理は大幅に変更されます。
- クライアントは最初にスロットに対応する古いノードにアクセスします
- データがまだ古いノードにある場合、古いノードは正常に処理されます
- データが古いノードに存在しなくなった場合、古いノードはアスクBリダイレクト順序をクライアントに返します
- クライアントは最初にaskBを実行します
- 次に、クライアントはget操作を実行します
リダイレクト時にgetを直接使用できないのに、最初にaskコマンドを発行するのはなぜですか?
スロットはノードBに属していない(まだノードAに属している)ため、getコマンドを直接送信すると、BはクライアントをAにリダイレクトし、循環リダイレクトを引き起こします。