天天看点

Spring Data Redis Redis集群---笔记5

继续。。。

6.Redis Cluster(Redis集群)

Redis集群需要版本3.0+,它提供一些特性和集群的能力,详情参考Redis官网

注意: Redis 集群目前只支持 jedis和lettuce。

6.1.Enabling Redis Cluster(开启redis集群)

集群支持是基于构建相同的块作为非集群通信。RedisClusterConnection扩展于RedisConnection。它处理集群通讯和异常转换成Spring DAO异常。

RedisClusterConnection是通过RedisConnectionFactory进行创建的。而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:逗号隔开分割多个host:port对

spring.redis.cluster.max-redirects:允许集群重导的数量

提示:

初始化配置指定驱动库去初始化集群节点。从激活的集群重新配置的结果只会存在原生驱动中不会写入到配置文件中。

6.2. Working With Redis Cluster Connection(与redis集群连接一起协作)

如上所述Redis集群和单个节点Redi或者甚至是一个主从关系Redis环境都是不一样的。这个原因就是Redis会自动分片。将会不同key映射到不同slot(槽)中,当然这些会分给不同的节点。因此命令在执行之前必须进行断言是否在相同的slot(槽)内,以避免执行出现错误,跟进一步说,所以单个集群节点,只有服务器才有keys集合单,命令下达到一个特定的服务器,它只返回这个服务器所有管理的key。这是一个非常简单的例子获取所有的keys。在集群环境下达一个命令到一个服务器,它只会通过这个节点进行发送特定的keys,当要获取所有的key的时候,你必须知道所有主节点。

当重定向一个特定keys到对应slot中,这个服务节点将会有driver库进行操作。更高级的功能例如从节点中收集信息或者发送命令到所有节点,这些都是RedisClusterConnection需要干的活。在之前获取keys例子,意思就是keys(pattern)方法将会获取每个主节点,同时在每个主节点执行KEYS命令。为了仅仅是请求单一节点,RedisClusterConnection提供重载这些方法(例如 keys(node, pattern)).

一个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.主节点管理的slots 从0到5460  备份到端口为7382

2.主节点管理的slots 从5461到10922

3.主节点管理的slots 从10923到16383

4.从节点备份端口号为7379的数据

5.请求路由到节点端口7381服务的slot12182

6.请求路由到节点端口7379服务的slot5061

7.请求路由到节点端口7379,7380,7381-》[foo,bar]

8.请求路由到节点端口7379-》[bar]

9.请求路由到节点端口7380-》【】

10.请求路由到节点端口7381-》[foo]

11.请求路由到节点端口7382-》[bar]

通过slot请求 例如当所有的key映射到相同slot,MGET通过原生驱动库将会自动获取服务。然而一旦不是这种情况,RedisClusterConnection执行多个平行的GET命令,获取多个节点slot的服务,最后返回一个累计的结果。这种性能肯定没有单个slot执行的效率高,所以在使用的时候必须小心。如果怀疑的话,请求考虑用在单个节点中 使用前缀和括弧,例如{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                      
7bb...           1
           
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.配置如上例子一样

2.Keys映射到相同的slot-》127.0.0.1:7381 MGET foo{foo}.bar

Keys映射到不同slots,分离到单个slot路由到对应的nodes

3.-》127.0.0.1:7379 GETbar

-》127.0.0.1:7379 GET foo

以上例子展示Spring Data Redis处理的一般策略。必须要考虑到某些操作可能会需要加载大量的数据到内存中。除此之外,并不是所有跨slot请求都是安全的,它也可能出现异常(例如命令PFCOUNT)。

6.3. Working With RedisTemplate and ClusterOperations(RedisTemplate集群操作)、

对于一般RedisTemplate的一般目的,配置以及使用,请参考Working with Objects through RedisTemplate的章节。

警告:

请谨慎设置RedisTemplate#keySerializer。它使用任何json相关RedisSerializers 作为改变json结构将会立即影响到hash slot计算。

RedisTemplate通过ClusterOperations 提供特殊的操作。它可以通过RedisTemplate.opsForCluster()获取。它允许在单个节点显式执行命令来获取序列化/反序列化特性。它提供高级管理命令例如Cluster MEET 或者 高级操作 例如 resharding(重新切片)

例子4. 通过RedisTemplate 获取RedisClusterConnection

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

解释:

1.关闭节点7379,然后从节点将会接管。

继续阅读