使用RedisSentinelConfiguration不会故障转移到下一个可用的sentinel / master

时间:2015-06-22 22:04:09

标签: spring redis spring-data spring-data-redis redis-sentinel

我正在尝试使用redis-sentinel为我的redis实例设置HA。我假设我的java应用程序必须使用RedisSentinelConfiguration来创建连接工厂。因此我设置了连接工厂,如下所示

@Bean(name = "redisConnectionFactory")
    public JedisConnectionFactory redisConnectionFactory() {
        String redisHost = redisSystemProperties.getProperty("redis.host");
        int redisPort = redisSystemProperties.getIntegerProperty("redis.port", DEFAULT_REDIS_PORT);
        logger.info(format("Creating redis connection factory.  host: %s, port: %d", redisHost, redisPort));
        JedisConnectionFactory connectionFactory = new JedisConnectionFactory(redisSentinelConfig(), jedisPoolConfig());
        boolean usePool = Boolean.valueOf(redisSystemProperties.getProperty("pool.enabled", "true"));
        connectionFactory.setUsePool(usePool);
        connectionFactory.afterPropertiesSet();
        return connectionFactory;
    }

    @Bean(name ="redisSentinelConfig")
    public RedisSentinelConfiguration redisSentinelConfig(){
        RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration();
        for (int i = 0; i < MAX_REDIS_MASTER_NODES; i++) {
            String hostPropertyName = format("redis.%d.host", i);
            String host = redisSystemProperties().getProperty(hostPropertyName);
            String portPropertyName = format("redis.%d.port", i);
            String portStr = redisSystemProperties().getProperty(portPropertyName);
            if (StrUtils.anyBlank(host, portStr)) {
                break;
            }
            int port = toInt(portStr);
            Assert.isTrue(port > 0, format("Invalid value '%s' for property '%s'", portStr, portPropertyName));
            RedisNode redisNode = new RedisNode(host, port);
            logger.info(format("Adding connection to redis sentinel [%d]: host: '%s', port: %d", i, host, port));
            sentinelConfig.addSentinel(redisNode);
            sentinelConfig.setMaster("mymaster");
        }
        return  sentinelConfig;
    }

用于创建RedisSentinelConfiguration的IP和端口号是我启动的Sentinel实例。我为每个主人开了一个哨兵。我有3个大师跑,所以3个哨兵。只要映射到sentinel'mymaster'的主节点正在运行,该应用程序似乎工作得很好。一旦我关闭该redis节点,应用程序就无法获得连接。我看到连接拒绝错误。在调试时,我可以看到它正在尝试使用它在第一次尝试中使用的单个Sentinel配置来创建连接。

这是我的哨兵配置。

port 26379

sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-milliseconds mymaster 1
sentinel failover-timeout mymaster 1
sentinel config-epoch mymaster 0
# Generated by CONFIG REWRITE
dir "/Users/skandula/redis-3.0.2"
sentinel leader-epoch mymaster 0
sentinel known-sentinel mymaster 127.0.0.1 26380 e4bc16a7435eec64512acc03404beb9799dea73e
sentinel known-sentinel mymaster 127.0.0.1 26381 493d598ce30dd4429bdc53c94cf297b8a0436c67
sentinel current-epoch 0

有人能让我知道我能做错什么吗?我正在使用spring-data-redis 1.5.0.RELEASE和Jedis-2.7.0

谢谢

1 个答案:

答案 0 :(得分:1)

故障转移与实际实施之间存在差距,以获取新选出的主节点。虽然Sentinel本身可能被配置为立即进行故障转移,但java驱动程序实现可能会略微落后。你需要照顾那些情况。

运行ContactsContract.Contacts.HAS_PHONE_NUMBER,您可以通过随机关闭Redis和/或Sentinel实例轻松探索行为,同时观察命令行打印错误以及实际恢复的时间。

您还可以使用sentinel example重新安排写入redis的尝试。有一张票(spring-retry)可以用来整合topic_id - 所以你可能想投票给它。