В случае применения горизонтального масштабирования сервисных служб DirectumRX необходимо использовать отказоустойчивую инсталляцию Redis для сервисных служб сервис хранилищ DirectumRX. В статье рассмотрим наиболее простой вариант реализации.
Redis – это система управления базами данных класса NoSQL (не реляционные СУБД), размещаемых целиком в оперативной памяти. Для доступа к данным используется модель «ключ» - «значение». Такая СУБД используется зачастую для хранения кэшей в масштабируемых сервисах, для хранения изображений и данных небольшого размера.
Широкое распространение СУБД Redis получила за счет:
Широту распространения и применимость Redis можно оценить по огромному количеству документации со всевозможными кейсами на официальном сайте проекта: https://redis.io/documentation.
В случае применения горизонтального масштабирования сервисных служб DirectumRX необходимо использовать отказоустойчивую инсталляцию Redis для корректной работы с сервисом хранилищ DirectumRX и сервисом веб-доступа DirectumRX.
В Redis будут храниться оперативные данные, кэши и прочая информация, которая необходима для работы служб, находящихся в режиме масштабирования, чтобы процесс взаимодействия пользователя с системой не зависел от инсталляции, с которой в текущий момент он работает.
В конфигурационных файлах служб необходимо указать необходимые параметры для подключения к Redis.
Для web-доступа:
<var name="ENABLE_SCALING" value="True"/>
<var name="REDIS_HOST" value="RedisHost"/>
<var name="REDIS_PORT" value="6379"/>
Для сервиса хранилищ:
<var name="STORAGE_SERVICE_ENABLED_SCALING" value="True" />
<var name="STORAGE_SERVICE_REDIS_HOST" value="RedisHost" />
<var name="STORAGE_SERVICE_REDIS_PORT" value="6379" />
ENABLE_SCALING и STORAGE_SERVICE_ENABLED_SCALING - признак включения горизонтального масштабирования.
REDIS_HOST и STORAGE_SERVICE_REDIS_HOST - путь до компьютера, на котором развернут экземпляр службы Redis.
REDIS_PORT и STORAGE_SERVICE_REDIS_PORT - порт, по которому сервис взаимодействует со службой Redis. Значение по умолчанию 6379.
На официальном сайте Redis выделяется 2 способа обеспечения отказоустойчивости:
Вариант с использованием Redis Sentiel (Следящий узел Redis) был реализован в версии Redis 2.4 и состоит в том, что для мониторинга доступности мастера используется дополнительный сервис Redis Sentiel. Он же выполняет настройку узлов реплик, в случае выхода из строя мастера. Определяет какой из SLAVE узлов станет MASTER и выполнит перенастройку на ходу.
Реализует классическую схему:
SLAVE-узлов может быть множество (до 1000 по данным с официального сайта), для продуктивной работы рекомендуется использовать не менее двух SLAVE-узлов.
Обычно схема настраивается таким образом, что на MASTER- и на SLAVE-узлах настраивается сервис Redis Sentiel и при выходе из строя MASTER-узла, оставшиеся следящие узлы принимают решение о введении в работу нового MASTER.
Вариант кластеризации Redis Cluster реализован для версии redis 3.0 и выше, является решением для создания и управления кластером с сегментацией и репликацией данных. Выполняет задачи управления узлами, репликации, синхронизации данных на узлах и обеспечения доступа клиентского приложения к MASTER-узлу в случае выхода из строя одного из нескольких MASTER-узлов.
Redis Cluster наиболее надежный вариант. Работает в режиме мультимастера, у каждого MASTER-узла может быть один или более SLAVE-узлов (до 1000).
Представленная схема требует, как минимум 3-6 узлов. Запросы перенаправляются от клиентов на нужный MASTER или SLAVE — но это требует поддержки режима кластера Redis самим клиентским приложением.
В данной статье будем рассматривать наиболее простой вариант – Redis Sentiel.
Актуальная версия Redis доступна для скачивания с официального сайта разработчика продукта https://redis.io/download. Однако на сайте доступен дистрибутив только для ОС Linux. В своё время развивался проект Microsoft по портированию Redis на ОС Windows (https://github.com/MicrosoftArchive/Redis), однако в настоящее время проект остановил развитие на версии 3.2.100, поэтому в данной статье будем рассматривать наиболее актуальный вариант разворачивания – на ОС Linux.
В качестве тестовых узлов будем использовать два виртуальных хоста redis1 и redis2 с установленным дистрибутивом Linux Debian 10.
Первым делом подключаем репозиторий Redis для получения актуальных версий:
1. Создадим файл /etc/apt/sources.list.d/dotdeb.list и пропишем адреса репозитория:
deb http://packages.dotdeb.org stable all
deb-src http://packages.dotdeb.org stable all
2. Получим GPG-ключ для работы с репозиторием:
wget https://www.dotdeb.org/dotdeb.gpg
apt-key add dotdeb.gpg
При необходимости, устанавливаем дополнительные компоненты:
apt install gnupg
3. Устанавливаем Redis:
apt install redis-server
Проверим версию:
root@redis1:/home/user# redis-server -v
Redis server v=5.0.3 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=afa0decbb6de285f
Пусть redis1 будет выступать в качестве MASTER-узла, а redis2 – в качестве SLAVE-узла.
Для этого в конфигурационных файлах Redis пропишем необходимые параметры, которые позволят создать реплику (пока не отказоустойчивую).
Для redis1 в конфигурационном файле /etc/redis/redis.conf указываем:
#указываем пароль, по которому MASTER будет разрешать работать с ним.
requirepass TestPass
Для redis2 в конфигурационном файле /etc/redis/redis.conf указываем:
# Указываем адрес MASTER и порт.
slaveof redis1 6379
# Указываем пароль для работы с мастером.
masterauth TestPass
# Также указываем пароль, чтобы с узлом можно было работать только по паролю.
requirepass TestPass
Выполним перезапуск сервисов redis-server на обоих узлах:
root@redis1:/etc/redis# /etc/init.d/redis-server stop
[ ok ] Stopping redis-server (via systemctl): redis-server.service.
root@redis1:/etc/redis# /etc/init.d/redis-server start
[ ok ] Starting redis-server (via systemctl): redis-server.service.
root@redis2:/etc/redis# /etc/init.d/redis-server stop
[ ok ] Stopping redis-server (via systemctl): redis-server.service.
root@redis2:/etc/redis# /etc/init.d/redis-server start
[ ok ] Starting redis-server (via systemctl): redis-server.service.
Проверяем на стороне MASTER, что узлы стали репликами и получили необходимые роли:
root@redis1:/etc/redis# redis-cli -a TestPass info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.9.96,port=6379,state=online,offset=28,lag=0
master_replid:56b0a702d5823d107b0ca1ca2c80f8ef650a4b28
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28
На стороне SLAVE видим такую же ситуацию:
root@redis2:/etc/redis# redis-cli -a TestPass info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:slave
master_host:redis1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
slave_repl_offset:14
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:56b0a702d5823d107b0ca1ca2c80f8ef650a4b28
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
Теперь необходимо настроить реплику таким образом, чтобы она автоматически восстанавливалась в случае выхода из строя одного из узлов. Для этого нам понадобиться следящий сервис Redis Sentinel.
Исходя из документации https://redis.io/topics/sentinel, следящий сервис Redis Sentinel умеет выполнять следующие операции:
Разместим для чистоты эксперимента следящий сервис на отдельную ВМ redis3.
Подключаем аналогичным способом репозиторий Redis и устанавливаем пакет redis-sentinel:
apt install redis-sentinel
После установки необходимо внести настройки в конфигурационный файл следящего узла /etc/redis/sentinel.conf:
# Настраиваем мониторинг узла redis1 по порту 6379.
# Последняя цифра 1 - означает количество следящих узлов в кворуме,
# мнение которых учитывается в случае необходимости изменить MASTER-узел.
# То есть можно поднять несколько следящих узлов,
# которые будут выполнять мониторинг MASTER-узла.
sentinel monitor master01 redis1 6379 1
# Ждем 3 секунды, прежде чем принимать решение о сбое узла.
sentinel down-after-milliseconds master01 3000
# Зададим таймаут восстановления MASTER-узла
sentinel failover-timeout master01 6000
# Указываем сколько SLAVE-узлов необходимо перенастраивать одновременно.
# Необходимо указывать минимальное количество, чтобы не получилось так,
# что все реплики станут недоступны одновременно.
sentinel parallel-syncs master01 1
# Обязательно прописываем прослушиваемые порты.
bind 192.168.9.97 127.0.0.1 ::1
# И прописываем пароль MASTER-узла.
sentinel auth-pass master01 TestPass
Перезапустим сервис после внесения настроек:
root@redis3:/etc/redis# /etc/init.d/redis-sentinel restart
[ ok ] Restarting redis-sentinel (via systemctl): redis-sentinel.service.
Проверим, что следящий сервис увидел MASTER и SLAVE:
root@redis3:/etc/redis# redis-cli -p 26379 info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=master01,status=ok,address=192.168.9.95:6379,slaves=1,sentinels=1
Начинаем эксперименты.
Сымитируем сбой, остановим сервис redis-server на узле redis1 и получим ткущую информацию следящего узла:
root@redis3:/etc/redis# redis-cli -p 26379 info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=master01,status=ok,address=192.168.9.96:6379,slaves=1,sentinels=1
Видим, MASTER поменялся.
Восстановим работу узла redis1 и проверим его состояние:
root@redis3:/var/log/redis# redis-cli -h redis1 -p 6379 -a TestPass info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:slave
master_host:192.168.9.96
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:15977
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:6c0c7d0eedccede56f211f2db74a98c4d0ff6d56
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:15977
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:15977
Видим, что узел получил роль SLAVE, а узел redis2 является MASTER-узлом.
Сымитируем сбой узла redis2 и проверим состояние следящего узла:
root@redis3:/var/log/redis# redis-cli -p 26379 info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=master01,status=ok,address=192.168.9.95:6379,slaves=1,sentinels=1
И состояние узла redis1:
root@redis3:/var/log/redis# redis-cli -h redis1 -p 6379 -a TestPass info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:0
master_replid:6e9d67d6460815b925319c2bafb58bf2c435cffb
master_replid2:6c0c7d0eedccede56f211f2db74a98c4d0ff6d56
master_repl_offset:33610
second_repl_offset:26483
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:33610
Отлично, механизм работает. Но теперь возникла проблема, как мы будем подключать наши сервисы DirectumRX, ведь для них нужен адрес единственного узла. Решим вопрос с помощью сервисной службы HAProxy.
В качестве reverse-прокси для узлов Redis может выступать любой проксирующий tcp-сервис. В данной статье рассмотрим использование HAProxy поскольку это специализированный инструмент предназначенный для обеспечения высокой доступности и балансировки нагрузки и используется повсеместно известными онлайн сервисами. Подробнее о HAProxy можно почитать на странице разработчика http://www.haproxy.org/#desc.
Установим HAProxy на узел redis3:
root@redis3:/var/log/redis# apt search haproxy
В конфигурационный файл HAProxy /etc/haproxy/haproxy.cfg, добавим настройки для проксирования запросов к узлам Redis:
…
frontend ft_redis
bind *:6379 name redis
mode tcp
default_backend bk_redis
backend bk_redis
mode tcp
option tcp-check
tcp-check connect
# Не забываем, что все узлы принимают запросы только при наличии пароля.
tcp-check send AUTH\ TestPass\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
# Работаем только с MASTER, т.к. SLAVE по умолчанию работает только на чтение.
tcp-check expect string role:master
tcp-check send QUIT\r\n
tcp-check expect string +OK
server Redis1 redis1:6379 check inter 3s
server Redis2 redis2:6379 check inter 3s
В данной конфигурации указано, что проксировать будем любые запросы, приходящие на все интерфейсы текущей виртуальной машины по адресу на порт 6379. Запросы будем передавать на узел, который ответит, что он имеет роль MASTER.
Перезапустим сервис haproxy:
root@redis3:/etc/haproxy# /etc/init.d/haproxy restart
Попробуем подключиться с помощью клиента redis-cli и создадим тестовый ключ:
root@redis3:/etc/haproxy# redis-cli -p 6379 -a TestPass
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> SET TestKey "Some test string"
OK
127.0.0.1:6379> GET TestKey
"Some test string"
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=1,expires=0,avg_ttl=0
Остановим узел redis1 и запросим снова список ключей:
127.0.0.1:6379> info keyspace
Error: Server closed the connection
(3.01s)
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=1,expires=0,avg_ttl=0
(2.01s)
Видим, что на некоторое время соединение оборвалось, но затем подключение снова восстановилось и все данные остались на месте.
Теперь достаточно прописать в конфигурационных файлах сервисов DirectumRX адрес reverse-прокси для подключения к Redis.
При настройке на реальной инсталляции, необходимо, чтобы следящих сервисов было несколько (по правилам на каждом узле реплики) и HAProxy работал в режиме кластера. В данной статье кластеризация HAProxy рассматриваться не будет, мы рассмотрели только основные принципы настройки отказоустойчивого Redis для сервисов DirectumRX.
Если статья наберет больше 30 лайков, продолжим данную тему и рассмотрим настройку Redis Cluster, а также в продолжении рассмотрим настройки балансировщиков на базе HAProxy и Ngnix применимо для DirectumRX.
Дисклеймер
Рекомендации представленные в статье не являются официальной документацией какой бы то ни было компании. Рекомендации предоставляются на основании личного опыта автора по настройке системы DirectumRX и серверных компонентов. Автор статьи не несет ответственности и не предоставляет гарантий в связи с публикацией фактов, сведений и другой информации, а также не предоставляет никаких заверений или гарантий относительно содержащихся здесь сведений.
Андрей, отличная статья!
Есть несколько вопросов:
1. судя из статьи получаем, что необходимо минимум 3 сервера для Redis и еще пара для HAProxy (тут кстати тоже возможно потребуется 3 следящий). Итого - минимум 5.
При этом внедрять планируется это все как минимум в отказоустойчивую/масштабируемую архитектуру DirectumRX, в которой итак будет минимум 4 сервера (2 на СУБД и 2 на сервер приложений). Возможно имеет смысл как-то совместить с уже используемыми серверами, тем более нагрузка на сервера с Redis судя по всему скорее низкая, чем высокая?
2. Есть ли опыт использования на продуктивных системах именно такой схемы отказоустойчивого Redis?
Алексей, спасибо за комментарий.
По сути это был эксперимент, пока на реальных проектах на сколько я знаю, еще такая схема не использовалось, коллеги думаю поправят если где-то уже что-то подобное есть.
Частичное совмещение возможно, к примеру HAProxy можно совместить с балансировщиком, только если балансировщик не вынесен в DMZ. Поскольку Redis для Windows больше не поддерживается, лучше разворачивать Redis на машинах с Linux, но если в качестве СУБД используется PostgreSQL на Linux, то возможность развертывания там экземпляров Redis можно рассмотреть.
>>однако в настоящее время проект остановил развитие на версии 3.0.504
немного поправлю: последняя актуальная версия для Windows 3.2.100, скачать можно по ссылке https://github.com/MicrosoftArchive/redis/releases/download/win-3.2.100/Redis-x64-3.2.100.msi,
но таки да, на этом Redis на Windows приостанавливает свою историю. И если хочется полной функциональности, то надо переходить на Linux-версии (хотя для DirectumRX на текущий момент достаточно и функциональности Win-версии).
Со своей стороны тоже немного погружался в вопрос и пришел примерно к следующим выводам:
И тут было бы интересно узнать мнение сообщества:
используется ли у кого-то отказоустойчивый/масштабируемый Redis в компании. Если да, то какая архитектура реализована у вас?
Алексей, спасибо за комментарий. Версию подправил в статье.
И да, согласен. Коллеги, если у кого-то есть опыт по настройкам Redis, пожалуйста отпишитесь в комментариях.
Postgres, elastic, redis, haproxy... Того и гляди следующий Директум будет на electron, nodejs и т. д.
А разве Redis Cluster является решения для отказоустойчивости? Это же горизонтальное масштабирование сервиса и инструмент повышения производительности. И это явно указано в той же документации. Да он закрывает вопросы в том числе и по отказоустойчивости, но изначальная его цель в другом, а отказоустойчивость приятный бонус.
Денис, да, все верно. Реализуем горизонтальное масштабирование и одновременно отказоустойчивость. В случае DirectumRX Redis не используется для работы с нагруженными данными, ценным является именно отказоустойчивость за счет кластеризации.
Авторизуйтесь, чтобы написать комментарий