赞
踩
Redis集群的行为与单节点Redis甚至Sentinel监控的master-replica环境不同。这是因为自动分片将key映射到16384个槽中的一个,这些槽分布在各节点中。因此,涉及多个key的命令必须断言(assert)所有key映射到完全相同的槽,以避免跨槽错误。单个集群节点仅提供一组专用keys。针对一个特定服务器发出的命令只返回该服务器提供的keys的结果。以KEYS命令作为一个简单的例子。当命令发布到集群环境中的服务器时,它只返回请求发送到的节点所匹配出的keys,而不返回集群中的所有符合条件的keys。因此,要获得集群环境中的所有keys,必须从所有已知的主节点读取keys。
虽然特定keys到相应槽服务节点(slot-serving node)的重定向由驱动程序库处理,但RedisClusterConnection涵盖了更高级别的功能,如跨节点收集信息或向群集中的所有节点发送命令。选取前面的keys示例,这意味着keys(pattern)方法选取集群中的每个主节点,并同时在每个主节点上运行keys命令,同时提取结果并返回累积的keys集合。如果只请求单个节点的keys,RedisClusterConnection为这些方法提供了重载(例如,keys(node, pattern))。
RedisClusterNode可以从RedisClusterConnection.clusterGetNodes获得,也可以使用主机和端口或节点Id来构建。
以下示例展示了在集群中运行的一组命令:
例1:在集群上运行命令示例
redis-cli@127.0.0.1:7379 > cluster nodes 1. 6b38bb... 127.0.0.1:7379 master - 0 0 25 connected 0-5460 2. 7bb78c... 127.0.0.1:7380 master - 0 1449730618304 2 connected 5461-10922 3. 164888... 127.0.0.1:7381 master - 0 1449730618304 3 connected 10923-16383 4. b8b5ee... 127.0.0.1:7382 slave 6b38bb... 0 1449730618304 25 connected RedisClusterConnection connection = connectionFactory.getClusterConnnection(); 5. connection.set("thing1", value); 6. connection.set("thing2", value); 7. connection.keys("*"); 8. connection.keys(NODE_7379, "*"); 9. connection.keys(NODE_7380, "*"); 10. connection.keys(NODE_7381, "*"); 11. connection.keys(NODE_7382, "*"); 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]
当所有key映射到同一槽时,native驱动程序库会自动提供跨槽请求,如MGET。然而,一旦情况并非如此,RedisClusterConnection就会对槽服务节点(slot-serving nodes)运行多个并行GET命令,并返回累积结果。这种方法的性能不如单槽方法,因此应谨慎使用。如果有疑问,可以考虑通过在花括号中提供前缀将keys固定到同一个槽,例如{my-prefix}.thing1和{my-prefix}.thing2,这两个前缀都将映射到同一槽编号。以下示例展示跨插槽请求处理:
例2:跨槽请求处理示例
redis-cli@127.0.0.1:7379 > cluster nodes 1. 6b38bb... 127.0.0.1:7379 master - 0 0 25 connected 0-5460 7bb... RedisClusterConnection connection = connectionFactory.getClusterConnnection(); connection.set("thing1", value); // slot: 12182 connection.set("{thing1}.thing2", value); // slot: 12182 connection.set("thing2", value); // slot: 5461 2. connection.mGet("thing1", "{thing1}.thing2"); 3. connection.mGet("thing1", "thing2"); 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所遵循的一般策略。请注意,有些操作可能需要将大量数据加载到内存中才能计算所需的命令。此外,并非所有跨槽请求都可以安全地移植到多个单槽请求,如果误用,则会出现错误(例如,PFCOUNT)。
有关RedisTemplate的一般用途、配置和用法的信息,请参阅“通过RedisTemplate处理对象”部分。
使用任何JSON RedisSerializers设置RedisTemplate#keySerializer时要小心,因为更改JSON结构会直接影响哈希槽计算。
RedisTemplate通过ClusterOperations接口提供对集群特定操作的访问,该接口可以从RedisTemplate.opsForCluster()获得。这使你可以在集群中的单个节点上显式运行命令,同时保留为template配置的序列化和反序列化功能。它还提供管理命令(如CLUSTER MEET)或更高级的操作(如resharding)。
以下示例展示如何使用RedisTemplate访问RedisClusterConnection:
例3:使用RedisTemplate访问RedisClusterConnection
ClusterOperations clusterOps = redisTemplate.opsForCluster();
1. clusterOps.shutdown(NODE_7379);
1. 关闭7379节点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。