Redis クラスター

Redis クラスター (英語) を使用するには、Redis サーバーバージョン 3.0 + が必要です。詳細については、クラスターチュートリアル (英語) を参照してください。

Redis リポジトリを Redis クラスターで使用する場合は、クラスター上で Redis リポジトリを実行する方法をよく理解しましょう。
Redis クラスターを使用する場合は、キースペースイベントに依存しないでください。キースペースイベントはシャード間で複製されないためです。Pub/Sub は、単一のシャードからのみキースペースイベントを受信するランダムクラスターノードにサブスクライブします [GitHub] (英語) 。キースペースイベントの損失を回避するには、単一ノードの Redis を使用します。

Redis クラスター接続の操作

Redis クラスターは、単一ノードの Redis や、Sentinel が監視するマスターレプリカ環境とは動作が異なります。これは、自動シャーディングによってキーが 16384 スロットの 1 つにマップされ、ノード全体に分散されるためです。複数のキーを含むコマンドは、クロススロットエラーを避けるために、すべてのキーがまったく同じスロットにマップされることをアサートする必要があります。単一のクラスターノードは、専用のキーセットのみを提供します。特定の 1 つのサーバーに対して発行されたコマンドは、そのサーバーによって提供されるキーに対する結果のみを返します。簡単な例として、KEYS コマンドを考えてみましょう。クラスター環境内のサーバーに発行されると、リクエストの送信先のノードによって提供されるキーのみが返され、必ずしもクラスター内のすべてのキーが返されるわけではありません。クラスター環境ですべてのキーを取得するには、既知のすべてのマスターノードからキーを読み取る必要があります。

対応するスロットサービングノードへの特定のキーのリダイレクトはドライバーライブラリによって処理されますが、ノード間で情報を収集したり、クラスター内のすべてのノードにコマンドを送信したりするなどの高レベルの機能は、RedisClusterConnection でカバーされます。前のキーの例を取得すると、これは、keys(pattern) メソッドがクラスター内のすべてのマスターノードを取得し、同時にすべてのマスターノードで KEYS コマンドを実行しながら、結果を取得して累積されたキーのセットを返すことを意味します。単一ノードのキーをリクエストするだけで、RedisClusterConnection はそれらのメソッド(たとえば、keys(node, pattern))にオーバーロードを提供します。

RedisClusterNode は、RedisClusterConnection.clusterGetNodes から取得することも、ホストとポートまたはノード ID を使用して構築することもできます。

次の例は、クラスター全体で実行されている一連のコマンドを示しています。

例 1: クラスター全体で実行されるコマンドのサンプル
[email protected] (英語)  :7379 > cluster nodes

6b38bb... 127.0.0.1:7379 master - 0 0 25 connected 0-5460                      (1)
7bb78c... 127.0.0.1:7380 master - 0 1449730618304 2 connected 5461-20242       (2)
164888... 127.0.0.1:7381 master - 0 1449730618304 3 connected 10923-20243      (3)
b8b5ee... 127.0.0.1:7382 slave 6b38bb... 0 1449730618304 25 connected          (4)
RedisClusterConnection connection = connectionFactory.getClusterConnnection();

connection.set("thing1", value);                                               (5)
connection.set("thing2", value);                                               (6)

connection.keys("*");                                                          (7)

connection.keys(NODE_7379, "*");                                               (8)
connection.keys(NODE_7380, "*");                                               (9)
connection.keys(NODE_7381, "*");                                               (10)
connection.keys(NODE_7382, "*");                                               (11)
1 スロット 0 〜 5460 にサービスを提供するマスターノードが 7382 のレプリカに複製されました
2 スロット 5461 から 10922 にサービスを提供するマスターノード
3 スロット 10923 から 16383 にサービスを提供するマスターノード
47379 でマスターのレプリカントを保持しているレプリカノード
5 リクエストは 7381 サービングスロット 12182 のノードにルーティングされました
6 リクエストは 7379 サービングスロット 5061 のノードにルーティングされました
77379, 7380, 7381 のノードにルーティングされたリクエスト→ [thing1、thing2]
8 リクエストは 7379 のノードにルーティングされました→ [thing2]
9 リクエストは 7380 のノードにルーティングされました→ []
10 リクエストは 7381 のノードにルーティングされました→ [thing1]
11 リクエストは 7382 のノードにルーティングされました→ [thing2]

すべてのキーが同じスロットにマップされると、ネイティブドライバーライブラリは、MGET などのクロススロットリクエストを自動的に処理します。ただし、これが当てはまらない場合、RedisClusterConnection はスロットサービングノードに対して複数の並列 GET コマンドを実行し、累積された結果を再び返します。これはシングルスロットアプローチよりもパフォーマンスが低いため、注意して使用する必要があります。疑わしい場合は、同じスロット番号にマップされる {my-prefix}.thing1 や {my-prefix}.thing2 などのプレフィックスをカーリー括弧に指定して、キーを同じスロットに固定することを検討してください。次の例は、クロススロットリクエストの処理を示しています。

例 2: クロススロットリクエスト処理のサンプル
[email protected] (英語)  :7379 > cluster nodes

6b38bb... 127.0.0.1:7379 master - 0 0 25 connected 0-5460                      (1)
7bb...
RedisClusterConnection connection = connectionFactory.getClusterConnnection();

connection.set("thing1", value);           // slot: 12182
connection.set("{thing1}.thing2", value);  // slot: 12182
connection.set("thing2", value);           // slot:  5461

connection.mGet("thing1", "{thing1}.thing2");                                  (2)

connection.mGet("thing1", "thing2");                                           (3)
1 前のサンプルと同じ構成。
2 キーは同じスロットにマップされます。→ 127.0.0.1:7381 MGETthing1 {thing1} .thing2
3 キーは異なるスロットにマップされ、対応するノードにルーティングされる単一のスロットに分割されます
→ 127.0.0.1:7379 GETthing2
→ 127.0.0.1:7381GETthing1
上記の例は、Spring Data Redis が続く一般的な戦略を示しています。一部の操作では、目的のコマンドを計算するために大量のデータをメモリにロードする必要がある場合があることに注意してください。さらに、すべてのクロススロットリクエストを複数のシングルスロットリクエストに安全に移植できるわけではなく、誤用するとエラーが発生します(たとえば、PFCOUNT)。

RedisTemplate および ClusterOperations の操作

RedisTemplate の汎用、構成、使用箇所については、RedisTemplate を介したオブジェクトの操作セクションを参照してください。

JSON RedisSerializers のいずれかを使用して RedisTemplate#keySerializer を設定する場合は、JSON 構造の変更がハッシュスロットの計算にすぐに影響するため、注意してください。

RedisTemplate は、RedisTemplate.opsForCluster() から取得できる ClusterOperations インターフェースを介してクラスター固有の操作へのアクセスを提供します。これにより、テンプレート用に構成された直列化および逆直列化機能を保持しながら、クラスター内の単一ノードでコマンドを明示的に実行できます。また、管理コマンド(CLUSTER MEET など)またはより高レベルの操作(再シャーディングなど)も提供します。

次の例は、RedisTemplate を使用して RedisClusterConnection にアクセスする方法を示しています。

例 3: RedisTemplate を使用した RedisClusterConnection へのアクセス
ClusterOperations clusterOps = redisTemplate.opsForCluster();
clusterOps.shutdown(NODE_7379);                                              (1)
17379 でノードをシャットダウンし、指を交差させると、引き継ぐことができるレプリカが配置されます。
Redis クラスターパイプラインは現在、クロススロットキーを使用する場合の次のコマンドを除き、Lettuce ドライバーを通じてのみサポートされています: renamerenameNXsortbLPopbRPoprPopLPushbRPopLPushinfosMovesIntersInterStoresUnionsUnionStoresDiffsDiffStore。同一スロットキーは完全にサポートされています。