Redis Cluster

使用 Redis Cluster 需要 Redis Server 3.0+ 版本。有关更多信息,请参阅 Cluster Tutorial

Working with Redis Cluster requires Redis Server version 3.0+. See the Cluster Tutorial for more information.

在将“ Redis Repositories”与 Redis 集群一起使用时,请熟悉如何“ run Redis Repositories on a Cluster”。

When using Redis Repositories with Redis Cluster, make yourself familiar with how to run Redis Repositories on a Cluster.

Working With Redis Cluster Connection

Redis 集群的行为与单节点 Redis 甚至哨兵监控的主从复制环境不同。这是因为自动分片将键映射到 16384 个插槽中的一个,这些槽分布在所有节点中。因此,涉及一个以上键的命令必须断言所有键都映射到与确切相同的插槽,以避免跨插槽错误。单个集群节点仅为一组专用的键提供服务。针对某个特定服务器发出的命令仅返回该服务器提供的那些键的结果。作为一个简单的示例,考虑 KEYS 命令。当在集群环境中的服务器上发出时,它仅返回请求发送到的节点提供的键,而不仅仅是集群中的所有键。因此,要获取集群环境中的所有键,你必须从所有已知的 master 节点读取键。

Redis Cluster behaves differently from single-node Redis or even a Sentinel-monitored master-replica environment. This is because the automatic sharding maps a key to one of 16384 slots, which are distributed across the nodes. Therefore, commands that involve more than one key must assert all keys map to the exact same slot to avoid cross-slot errors. A single cluster node serves only a dedicated set of keys. Commands issued against one particular server return results only for those keys served by that server. As a simple example, consider the KEYS command. When issued to a server in a cluster environment, it returns only the keys served by the node the request is sent to and not necessarily all keys within the cluster. So, to get all keys in a cluster environment, you must read the keys from all the known master nodes.

虽然特定键到相应的插槽提供节点的重定向是由驱动程序库处理的,但诸如收集所有节点上的信息或向集群中的所有节点发送命令之类的更高级功能由 RedisClusterConnection 涵盖。从前面的键示例中,这意味着 keys(pattern) 方法选取集群中的每个 master 节点,同时在每个 master 节点上运行 KEYS 命令,同时选取结果并返回累积的键集合。为了仅仅请求单个节点的键,RedisClusterConnection 为这些方法提供了重载(例如,keys(node, pattern))。

While redirects for specific keys to the corresponding slot-serving node are handled by the driver libraries, higher-level functions, such as collecting information across nodes or sending commands to all nodes in the cluster, are covered by RedisClusterConnection. Picking up the keys example from earlier, this means that the keys(pattern) method picks up every master node in the cluster and simultaneously runs the KEYS command on every master node while picking up the results and returning the cumulated set of keys. To just request the keys of a single node RedisClusterConnection provides overloads for those methods (for example, keys(node, pattern)).

可以从 RedisClusterConnection.clusterGetNodes 获得 RedisClusterNode,也可以使用主机和端口或节点 ID 构建它。

A RedisClusterNode can be obtained from RedisClusterConnection.clusterGetNodes or it can be constructed by using either the host and the port or the node Id.

下面的示例展示了一组命令在集群中运行的情况:

The following example shows a set of commands being run across the cluster:

Example 1. Sample of Running Commands Across the Cluster
redis-cli@127.0.0.1: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 Master node serving slots 0 to 5460 replicated to replica at 7382
2 Master node serving slots 5461 to 10922
3 Master node serving slots 10923 to 16383
4 Replica node holding replicants of the master at 7379
5 Request routed to node at 7381 serving slot 12182
6 Request routed to node at 7379 serving slot 5061
7 Request routed to nodes at 7379, 7380, 7381 → [thing1, thing2]
8 Request routed to node at 7379 → [thing2]
9 Request routed to node at 7380 → []
10 Request routed to node at 7381 → [thing1]
11 Request routed to node at 7382 → [thing2]

当所有键映射到同一插槽时,本机驱动程序库会自动提供跨插槽请求,例如 MGET。然而,一旦不再是这种情况,RedisClusterConnection 会针对插槽提供节点运行多个并行的 GET 命令,并再次返回累积的结果。这不如单插槽方法高效,因此应谨慎使用。如有疑问,请考虑通过提供用花括号括起的键前缀来将键固定到同一插槽,例如 {my-prefix}.thing1{my-prefix}.thing2,这两个都将映射到相同的插槽号。下面的示例展示了跨插槽请求处理:

When all keys map to the same slot, the native driver library automatically serves cross-slot requests, such as MGET. However, once this is not the case, RedisClusterConnection runs multiple parallel GET commands against the slot-serving nodes and again returns an accumulated result. This is less performant than the single-slot approach and, therefore, should be used with care. If in doubt, consider pinning keys to the same slot by providing a prefix in curly brackets, such as {my-prefix}.thing1 and {my-prefix}.thing2, which will both map to the same slot number. The following example shows cross-slot request handling:

Example 2. Sample of Cross-Slot Request Handling
redis-cli@127.0.0.1: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 Same Configuration as in the sample before.
2 Keys map to same slot → 127.0.0.1:7381 MGET thing1 {thing1}.thing2
3 Keys map to different slots and get split up into single slot ones routed to the according nodes → 127.0.0.1:7379 GET thing2 → 127.0.0.1:7381 GET thing1

前面的示例演示了 Spring Data Redis 遵循的通用策略。请注意,某些操作可能需要将大量数据加载到内存中以计算所需的命令。此外,并非所有跨槽请求都能安全地移植到多个单槽请求,并且如果使用不当会出错(例如,PFCOUNT)。

The preceding examples demonstrate the general strategy followed by Spring Data Redis. Be aware that some operations might require loading huge amounts of data into memory to compute the desired command. Additionally, not all cross-slot requests can safely be ported to multiple single slot requests and error if misused (for example, PFCOUNT).

Working with RedisTemplate and ClusterOperations

有关 RedisTemplate 的一般用途、配置和使用情况,请参阅 Working with Objects through RedisTemplate 部分。

See the Working with Objects through RedisTemplate section for information about the general purpose, configuration, and usage of RedisTemplate.

使用任何 JSON RedisSerializers 设置 RedisTemplate#keySerializer 时要小心,因为更改 JSON 结构会立即影响哈希槽计算。

Be careful when setting up RedisTemplate#keySerializer using any of the JSON RedisSerializers, as changing JSON structure has immediate influence on hash slot calculation.

RedisTemplate 通过 ClusterOperations 接口提供对特定集群操作的访问,该接口可以从 RedisTemplate.opsForCluster() 获得。这允许你在集群中的单个节点上显式运行命令,同时保留为模板配置的序列化和反序列化功能。它还提供管理命令(例如 CLUSTER MEET)或更高级别的操作(例如重新分片)。

RedisTemplate provides access to cluster-specific operations through the ClusterOperations interface, which can be obtained from RedisTemplate.opsForCluster(). This lets you explicitly run commands on a single node within the cluster while retaining the serialization and deserialization features configured for the template. It also provides administrative commands (such as CLUSTER MEET) or more high-level operations (for example, resharding).

下面的示例展示了如何使用 RedisTemplate 访问 RedisClusterConnection

The following example shows how to access RedisClusterConnection with RedisTemplate:

Example 3. Accessing RedisClusterConnection with RedisTemplate
ClusterOperations clusterOps = redisTemplate.opsForCluster();
clusterOps.shutdown(NODE_7379);                                              1
1 Shut down node at 7379 and cross fingers there is a replica in place that can take over.