Использование RedisSentinelConfiguration не переключается на следующий доступный Sentinel/master.

Я пытаюсь настроить высокую доступность для своих экземпляров Redis, используя redis-sentinel. Я предполагаю, что мое 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;
    }

IP-адрес и номера портов, которые используются для создания RedisSentinelConfiguration, относятся к экземплярам Sentinel, которые я запустил. Я запустил часового для каждого мастера. У меня работает 3 мастера, а также 3 стража. Приложение, похоже, работает отлично, пока работает главный узел, сопоставленный с дозорным «mymaster». Как только я ЗАКРЫВАЮ этот узел перераспределения, приложение не может установить соединение. Я вижу ошибку отказа в соединении. Во время отладки я вижу, что он пытается создать соединение, используя единственную конфигурацию 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.

Спасибо


person Srini Kandula    schedule 22.06.2015    source источник


Ответы (1)


Существует разрыв между отработкой отказа и фактической реализацией, чтобы забрать вновь избранный главный узел. Хотя сам Sentinel может быть настроен на немедленное переключение при отказе, реализация драйвера Java, вероятно, будет немного отставать. Вам нужно будет позаботиться о таких ситуациях.

Запустив пример Sentinel, вы можете легко исследуйте поведение, случайным образом закрывая экземпляры Redis и/или Sentinel, наблюдая, как командная строка выводит ошибки и сколько времени на самом деле заняло восстановление.

Вы также можете использовать spring-retry, чтобы перепланировать попытки записи в Redis. Открыта заявка (DATAREDIS-370) на интеграцию RetryTemplate. Возможно, вы захотите проголосовать. для этого.

person Christoph Strobl    schedule 23.06.2015
comment
Я думаю, что у меня такая же точная конфигурация в моем приложении. Я вижу, что часовой теряет соединение и повторяет попытку, но похоже, что он не пытается с доступными часовыми. Вот что я вижу в журнале СЕРЬЕЗНО: Потеряно соединение с Sentinel по адресу 127.0.0.1:26379. Сон 5000 мс и повторная попытка. 23 июня 2015 г., 10:25:32 redis.clients.jedis.JedisSentinelPool$MasterListener run СЕРЬЕЗНО: потеряно соединение с Sentinel по адресу 127.0.0.1:26379. Сон 5000 мс и повторная попытка. Вы видите что-то не так с моей конфигурацией часового? - person Srini Kandula; 23.06.2015
comment
Я понял это. На самом деле это моя конфигурация, которая неверна. Мне не нужно было делать кластеризацию. Репликация Redis и достаточное количество дозорных процессов для мониторинга сервера — вот что мне было нужно. И да, весенняя повторная попытка действительно удобна. Я постараюсь сделать сообщение в блоге и дать ссылку на него здесь. Спасибо, Крис. Весенние СКАЛЫ. - person Srini Kandula; 23.06.2015
comment
Кстати, когда я обновился до spring-data-redis 1.0.5, моя сборка Gradle удалила зависимость от jedis. Я бы получил ошибку компиляции из-за того, что не нашел JedisPoolConfig. Мне пришлось явно добавить эту зависимость в мою сборку. - person Srini Kandula; 23.06.2015