Redis Sentinel мастер не понижен до раба сразу

У меня есть архитектура с тремя экземплярами Redis (один ведущий и два ведомых) и тремя экземплярами Sentinel. Перед ним есть HaProxy. Все работает хорошо, пока основной экземпляр Redis не выйдет из строя. Новый мастер правильно выбран Sentinel. Тем не менее, старый мастер (который сейчас не работает) не переконфигурирован как раб. В результате, когда этот экземпляр снова работает, у меня есть два мастера на короткий промежуток времени (около 11 секунд). После этого времени тот экземпляр, который был воспитан, должным образом понижен до уровня рабов.

Разве это не должно работать таким образом, что, когда мастер уходит, он сразу же становится рабом? Имея это, когда он снова встал, он немедленно стал бы рабом. Я знаю, что (начиная с Redis 2.8?) Есть эта функция CONFIG REWRITE, поэтому конфигурация не может быть изменена, когда экземпляр Redis не работает.

Наличие двух мастеров в течение некоторого времени является проблемой для меня, потому что HaProxy в течение этого короткого промежутка времени вместо отправки запросов одному мастеру Redis выполняет распределение нагрузки между этими двумя мастерами.

Есть ли способ понизить неисправного мастера до немедленного подчинения?

Очевидно, я изменил тайм-ауты Sentinel.

Вот некоторые журналы от экземпляров Sentinel и Redis после того, как мастер выйдет из строя:

часовой

81358:X 23 Jan 22:12:03.088 # +sdown master redis-ha 127.0.0.1                       63797.0.0.1 26381 @ redis-ha 127.0.0.1 6379
81358:X 23 Jan 22:12:03.149 # +new-epoch 1
81358:X 23 Jan 22:12:03.149 # +vote-for-leader 6b5b5882443a1d738ab6849ecf4bc6b9b32ec142 1
81358:X 23 Jan 22:12:03.174 # +odown master redis-ha 127.0.0.1 6379 #quorum 3/2
81358:X 23 Jan 22:12:03.174 # Next failover delay: I will not start a failover before Sat Jan 23 22:12:09 2016
81358:X 23 Jan 22:12:04.265 # +config-update-from sentinel 127.0.0.1:26381 127.0.0.1 26381 @ redis-ha 127.0.0.1 6379
81358:X 23 Jan 22:12:04.265 # +switch-master redis-ha 127.0.0.1 6379 127.0.0.1 6381
81358:X 23 Jan 22:12:04.266 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ redis-ha 127.0.0.1 6381
81358:X 23 Jan 22:12:04.266 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ redis-ha 127.0.0.1 6381
81358:X 23 Jan 22:12:06.297 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ redis-ha 127.0.0.1 6381

Redis

81354:S 23 Jan 22:12:03.341 * MASTER <-> SLAVE sync started
81354:S 23 Jan 22:12:03.341 # Error condition on socket for SYNC: Connection refused
81354:S 23 Jan 22:12:04.265 * Discarding previously cached master state.
81354:S 23 Jan 22:12:04.265 * SLAVE OF 127.0.0.1:6381 enabled (user request from 'id=7 addr=127.0.0.1:57784 fd=10 name=sentinel-6b5b5882-cmd age=425 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=14 qbuf-free=32754 obl=36 oll=0 omem=0 events=rw cmd=exec')
81354:S 23 Jan 22:12:04.265 # CONFIG REWRITE executed with success.
81354:S 23 Jan 22:12:04.371 * Connecting to MASTER 127.0.0.1:6381
81354:S 23 Jan 22:12:04.371 * MASTER <-> SLAVE sync started
81354:S 23 Jan 22:12:04.371 * Non blocking connect for SYNC fired the event.
81354:S 23 Jan 22:12:04.371 * Master replied to PING, replication can continue...
81354:S 23 Jan 22:12:04.371 * Partial resynchronization not possible (no cached master)
81354:S 23 Jan 22:12:04.372 * Full resync from master: 07b3c8f64bbb9076d7e97799a53b8b290ecf470b:1
81354:S 23 Jan 22:12:04.467 * MASTER <-> SLAVE sync: receiving 860 bytes from master
81354:S 23 Jan 22:12:04.467 * MASTER <-> SLAVE sync: Flushing old data
81354:S 23 Jan 22:12:04.467 * MASTER <-> SLAVE sync: Loading DB in memory
81354:S 23 Jan 22:12:04.467 * MASTER <-> SLAVE sync: Finished with success

5 ответов

Я также получал ту же ошибку, когда я хочу переключить мастер в Redis-кластере с помощью Sentinel.

+ голосование за лидера xxxxxxxxxxxxxxxxxxxxxxxx8989 10495
Следующая задержка при отказе: я не начну аварийное переключение до пт 2 августа 23:23:44 2019

После сброса часового. Кластер работает как положено

SENTINEL RESET *

или же

SENTINEL RESET мой мастер

Запустите вышеуказанную команду на всех часовых серверах.

При использовании haproxy более стабильным решением будет проверка доступных ведомых устройств. После перезагрузки, перезапуска или принудительного переключения старый мастер по-прежнему будет иметь роль мастера, но ведомые устройства не будут подключены. Таким образом, значение равно нулю.

      # faulty old master
role:master
connected_slaves:0
slave0:ip=127.0.0.2,port=6379,state=online,offset=507346829,lag=0
slave1:ip=127.0.0.1,port=6379,state=online,offset=507346966,lag=0
master_failover_state:no-failover
...

я бы заменил

          tcp-check expect string role:master
    tcp-check send info\ server\r\n
    tcp-check expect rstring uptime_in_seconds:\d{2,}

с

      tcp-check expect rstring connected_slaves:[^0]

Полный конфиг для меня.

      listen listen-REDIS
        bind 1.1.1.1:6379
        mode tcp
        no option prefer-last-server
        option tcplog
        balance leastconn
        option tcp-check
        tcp-check send "auth STRING\r\n"
        tcp-check send PING\r\n
        tcp-check expect string +PONG
        tcp-check send info\ replication\r\n
        tcp-check expect rstring connected_slaves:[^0]
        tcp-check send QUIT\r\n
        tcp-check expect string +OK
        default-server inter 500ms fall 1 rise 1
        server REDIS01 127.0.0.1:6379 check
        server REDIS02 127.0.0.2:6379 check
        server REDIS03 127.0.0.3:6379 check

Решение

Это можно решить, используя параметр повышения в конфигурации HAProxy.

      default-server check inter 1s fall 2 rise 30

# OR

server redis-1 127.0.0.1:6379 check inter 1s fall 2 rise 30

Это устанавливает количество успешных проверок, которые должны пройти, чтобы сервер считался работающим. Таким образом, это может успешно отсрочить повторное присоединение узла Redis к рассмотрению как UP и дать Sentinel возможность изменить роль узла.

Важный компромисс

Компромисс с этим подходом заключается в том, что HAProxy будет учитывать ваши аварийные переключения дольше, поскольку вы добавляете дополнительную задержку. Эта задержка применяется как к вашему повторно присоединяющемуся узлу после сбоя, так и к вашим существующим подчиненным узлам, которые повышаются доrole:master. В конечном итоге вам нужно будет сделать выбор между тем, какой вариант лучше для вас; наличие 2 мастеров на мгновение или отказ между узлами занимает больше времени.

Если узел Redis выходит из строя, когда / если он восстанавливается, он восстанавливается с тем же role это было до спуска. Страж не может перенастроить узел, если он не может пропинговать его. Таким образом, существует короткий промежуток времени между возвращением узла в исходное состояние и тем, что Sentinel подтверждает и реконфигурирует его. Это объясняет состояние нескольких мастеров.

Если вы настроены на использование Haproxy, одним из обходных путей будет перенастройка роли узла Redis до начала процесса. Redis будет загружаться как slave, если в redis.conf есть запись SLAVEOF. Основной проблемой этого обходного пути является то, что он не решает сценарии сетевых разделов.

Надеюсь, это поможет.

При использовании HAProxy вы можете попробовать запросить uptime_in_seconds что-то вроде этого:

      backend redis
    mode tcp
    balance first
    timeout queue 5s
    default-server check inter 1s fall 2 rise 2 maxconn 100
    option tcp-check
    tcp-check connect
    tcp-check send AUTH\ <secret>\r\n
    tcp-check expect string +OK
    tcp-check send PING\r\n
    tcp-check expect string +PONG
    tcp-check send info\ replication\r\n
    tcp-check expect string role:master
    tcp-check send info\ server\r\n
    tcp-check expect rstring uptime_in_seconds:\d{2,}
    tcp-check send QUIT\r\n
    tcp-check expect string +OK
    server redis-1 10.0.0.10:9736
    server redis-2 10.0.0.20:9736
    server redis-3 10.0.0.30:9736

Обратите внимание на:

        tcp-check expect rstring uptime_in_seconds:\d{2,}

если время безотказной работы не превышает 10 секунд, узел не будет добавлен

Другие вопросы по тегам