7. Redis 集群

使用Redis集群需要Redis服务器版本3.0+,并提供了一套自己的特性和功能。 有关更多信息,请参阅集群教程

7.1. 启用 Redis 集群

集群支持基于与非集群通信相同的构件块。 RedisClusterConnection是RedisConnection的扩展,用于处理与Redis集群的通信,并将错误转换为Spring DAO异常层次结构。 RedisClusterConnection是通过RedisConnectionFactory创建的,必须使用相应的RedisClusterConfiguration进行设置。

示例1. Redis集群的示例RedisConnectionFactory配置

@Component
@ConfigurationProperties(prefix = "spring.redis.cluster")
public class ClusterConfigurationProperties {

    /*
     * spring.redis.cluster.nodes[0] = 127.0.0.1:7379
     * spring.redis.cluster.nodes[1] = 127.0.0.1:7380
     * ...
     */
    List<String> nodes;

    /**
     * Get initial collection of known cluster nodes in format {@code host:port}.
     *
     * @return
     */
    public List<String> getNodes() {
        return nodes;
    }

    public void setNodes(List<String> nodes) {
        this.nodes = nodes;
    }
}

@Configuration
public class AppConfig {

    /**
     * Type safe representation of application.properties
     */
    @Autowired ClusterConfigurationProperties clusterProperties;

    public @Bean RedisConnectionFactory connectionFactory() {

        return new JedisConnectionFactory(
            new RedisClusterConfiguration(clusterProperties.getNodes()));
    }
}

RedisClusterConfiguration也可以通过PropertySource来定义

配配置属性

  • spring.redis.cluster.nodes:逗号分隔的主机:端口对列表。
  • spring.redis.cluster.max-redirects:允许的群集重定向次数。

初始配置将驱动程序库指向最初的一组集群节点。 活动群集重新配置所产生的更改只会保留在本机驱动程序中,而不会写回到配置中。

7.2. 使用Redis集群连接

如上所述,Redis集群的行为与单个节点Redis或甚至Sentinel监控的主从属环境有所不同。 这是由自动分片的原因,该分片将Key映射到分布在节点上的16384个插槽(slot)之一。 因此,涉及多于一个Key的命令必须声明所有Key映射到完全相同的插槽(slot)以避免交叉插槽(slot)执行错误。 进一步说,因此一个集群节点只提供专用的一组Key,对一个特定的服务器发出的命令只返回服务器提供的那些Key的结果。 作为一个非常简单的例子,使用KEYS命令。 当发布到集群环境中的服务器时,它只返回请求发送到的节点所服务的Key,而不一定是集群内的所有Key。 因此,要获得群集环境中的所有Key,至少需要从所有已知主节点读取Key。

虽然重定向到对应的槽服务节点的特定密钥由驱动程序库处理,但高级功能(如收集跨节点的信息)或向RedisClusterConnection覆盖的群集中的所有节点发送命令。 从上面的例子中,我们可以看到key(pattern)方法拾取簇中的每个主节点,并同时对每个主节点执行KEYS命令,同时拿起结果并返回累积的一组键。 为了只请求单个节点的密钥,RedisClusterConnection为那些(比如密钥(节点,模式))提供了重载。

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

示例2.跨集群运行命令的示例

[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-10922           (2)
164888... 127.0.0.1:7381 master - 0 1449730618304 3 connected 10923-16383          (3)
b8b5ee... 127.0.0.1:7382 slave 6b38bb... 0 1449730618304 25 connected              (4)
RedisClusterConnection connection = connectionFactory.getClusterConnnection();

connection.set("foo", value);                                                      (5)
connection.set("bar", 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 slave at 7382

(2) Master node serving slots 5461 to 10922

(3) Master node serving slots 10923 to 16383

(4) Slave node holding replicates of 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 → [foo, bar]

(8) Request routed to node at 7379 → [bar]

(9) Request routed to node at 7380 → []

(10) Request routed to node at 7381 → [foo]

(11) Request routed to node at 7382 → [bar]

所有Key映射到同一个插槽(slot)时,本地驱动程序库将自动为跨插槽(slot)请求(如MGET)提供服务。 但是,一旦情况不是这样,RedisClusterConnection将针对插槽(slot)服务节点执行多个并行GET命令,并再次返回累计结果。 显然这比单个时隙执行的性能差,因此应该小心使用。 如有疑问,请考虑在同一个插槽上提供一个前缀,如{my-prefix} .foo和{my-prefix} .bar,它们都映射到相同的插槽(slot)编号。

例子3.跨插槽(slot)请求处理的例子

[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("foo", value);         // slot: 12182
connection.set("{foo}.bar", value);   // slot: 12182
connection.set("bar", value);         // slot:  5461

connection.mGet("foo", "{foo}.bar");                                           (2)

connection.mGet("foo", "bar");                                                 (3)

(1) Same Configuration as in the sample before.

(2) Keys map to same slot → 127.0.0.1:7381 MGET foo {foo}.bar

Keys map to different slots and get split up into single slot ones routed to the according nodes

(3) → 127.0.0.1:7379 GET bar

→ 127.0.0.1:7381 GET foo

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

7.3. 使用RedisTemplate和ClusterOperations

请参阅通过RedisTemplate使用对象一节来了解RedisTemplate的一般用途,配置和用法。

使用任何JSON RedisSerializer设置RedisTemplate#keySerializer时请小心,因为更改json结构会对散列槽计算产生直接影响。

RedisTemplate通过可以通过RedisTemplate.opsForCluster()获取的ClusterOperations接口提供对集群特定操作的访问。 这允许在集群内的单个节点上显式地执行命令,同时保留为模板配置的解除/序列化功能,并提供管理命令,例如CLUSTER MEET或更高级别的操作。resharding。

示例4.通过RedisTemplate访问RedisClusterConnection

ClusterOperations clusterOps = redisTemplate.opsForCluster();
clusterOps.shutdown(NODE_7379);                                   (1)

(1) Shut down node at 7379 and cross fingers there is a slave in place that can take over.

results matching ""

    No results matching ""