Redis Cluster
使用 Redis Cluster 需要 Redis Server 3.0+ 版本。有关更多信息,请参阅 Cluster Tutorial。
在将“ Redis Repositories”与 Redis 集群一起使用时,请熟悉如何“ run Redis Repositories on a Cluster”。 |
Working With Redis Cluster Connection
Redis 集群的行为与单节点 Redis 甚至哨兵监控的主从复制环境不同。这是因为自动分片将键映射到 16384
个插槽中的一个,这些槽分布在所有节点中。因此,涉及一个以上键的命令必须断言所有键都映射到与确切相同的插槽,以避免跨插槽错误。单个集群节点仅为一组专用的键提供服务。针对某个特定服务器发出的命令仅返回该服务器提供的那些键的结果。作为一个简单的示例,考虑 KEYS
命令。当在集群环境中的服务器上发出时,它仅返回请求发送到的节点提供的键,而不仅仅是集群中的所有键。因此,要获取集群环境中的所有键,你必须从所有已知的 master 节点读取键。
虽然特定键到相应的插槽提供节点的重定向是由驱动程序库处理的,但诸如收集所有节点上的信息或向集群中的所有节点发送命令之类的更高级功能由 RedisClusterConnection
涵盖。从前面的键示例中,这意味着 keys(pattern)
方法选取集群中的每个 master 节点,同时在每个 master 节点上运行 KEYS
命令,同时选取结果并返回累积的键集合。为了仅仅请求单个节点的键,RedisClusterConnection
为这些方法提供了重载(例如,keys(node, pattern)
)。
可以从 RedisClusterConnection.clusterGetNodes
获得 RedisClusterNode
,也可以使用主机和端口或节点 ID 构建它。
下面的示例展示了一组命令在集群中运行的情况:
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 | 主节点分发 0 至 5460 的插槽,复制到 7382 的副本节点 |
2 | 主节点分发 5461 至 10922 的插槽 |
3 | 主节点分发 10923 至 16383 的插槽 |
4 | 7379 的副本节点持有主节点的副本 |
5 | 请求路由到 7381 分发 12182 插槽的节点 |
6 | 请求路由到 7379 分发 5061 插槽的节点 |
7 | 请求路由到 7379、7380、7381 节点 → [thing1、thing2] |
8 | 请求路由到 7379 节点 → [thing2] |
9 | 请求路由到 7380 节点 → [] |
10 | 请求路由到 7381 节点 → [thing1] |
11 | 请求路由到 7382 节点 → [thing2] |
当所有键映射到同一插槽时,本机驱动程序库会自动提供跨插槽请求,例如 MGET
。然而,一旦不再是这种情况,RedisClusterConnection
会针对插槽提供节点运行多个并行的 GET
命令,并再次返回累积的结果。这不如单插槽方法高效,因此应谨慎使用。如有疑问,请考虑通过提供用花括号括起的键前缀来将键固定到同一插槽,例如 {my-prefix}.thing1
和 {my-prefix}.thing2
,这两个都将映射到相同的插槽号。下面的示例展示了跨插槽请求处理:
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 | 与之前示例中的配置相同。 |
2 | 键映射到同一插槽 → 127.0.0.1:7381 MGET thing1 {thing1} .thing2 |
3 | 键映射到不同插槽且被拆分为路由到对应节点的单插槽键 → 127.0.0.1:7379 GET thing2→ 127.0.0.1:7381 GET thing1 |
前面的示例演示了 Spring Data Redis 遵循的通用策略。请注意,某些操作可能需要将大量数据加载到内存中以计算所需的命令。此外,并非所有跨槽请求都能安全地移植到多个单槽请求,并且如果使用不当会出错(例如, |
Working with RedisTemplate
and ClusterOperations
有关 RedisTemplate
的一般用途、配置和使用情况,请参阅 Working with Objects through RedisTemplate 部分。
使用任何 JSON RedisSerializers
设置 RedisTemplate#keySerializer
时要小心,因为更改 JSON 结构会立即影响哈希槽计算。
RedisTemplate
通过 ClusterOperations
接口提供对特定集群操作的访问,该接口可以从 RedisTemplate.opsForCluster()
获得。这允许你在集群中的单个节点上显式运行命令,同时保留为模板配置的序列化和反序列化功能。它还提供管理命令(例如 CLUSTER MEET
)或更高级别的操作(例如重新分片)。
下面的示例展示了如何使用 RedisTemplate
访问 RedisClusterConnection
:
RedisClusterConnection
with RedisTemplate
ClusterOperations clusterOps = redisTemplate.opsForCluster();
clusterOps.shutdown(NODE_7379); 1
1 | 关闭 7379 节点并祈祷已就位并可以接管的副本节点。 |