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 секунд, узел не будет добавлен