Установка и настройка кластера Redis в Linux

Кластер Redis часто используется в качестве инструмента для хранения данных их кэширования, брокера сообщений и других задач. Он стал популярным инструментом благодаря возможности масштабирования и высокой скорости работы. В этой статье представлены инструкции по созданию кластера на трех серверах для организации разделения данных (sharding) и высокой доступности за счет репликации. В данной конфигурации в случае отказа узла master, slave-сервер автоматически заменяет его.

Данная статья является переводом и адаптацией англоязычной статьи.

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

Установка Redis на каждый сервер

В зависимости от используемой версии Linux, может быть доступна установка Redis через менеджер пакетов. В данном руководстве мы рассмотрим установку текущей стабильной версии из исходного кода.

Сначала установите зависимости необходимые для сборки зависимости:

sudo apt-get update && sudo apt-get upgrade
sudo apt install make gcc libc6-dev tcl

Скачайте текущую стабильную ветку и извлеките исходный код из архива:

wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
sudo make install

Убедитесь, что тесты сборки проходят успешно:

make test

При успешном завершении, в консоли будет ответ:

\o/ All tests passed without errors!

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

Настройка узлов Master и Slave

В данной инструкции каждый master будет подключен к одному slave.

Для более удобной работы с несколькими терминалами рекомендуем использовать tmux.

Официальная документация рекомендует использовать 6 узлов — по одному экземпляру Redis на узле, что позволяет обеспечить большую надежность, но возможно использовать три узла со следующей топологией соединений:

В установке используется три сервера, на каждом из которых запущено по два экземпляра Redis. Убедитесь, что каждый хост независим от других и не выйдет из строя совместно с другим. Далее выполните следующие шаги:

Подключитесь по SSH к серверу 1. Перейдите в redis-stable/ и скопируйте redis.conf. В нашей инструкции имена файлов конфигураций соответствуют именам на изображении выше.

cp redis.conf c_slave.conf
mv redis.conf a_master.conf

В a_master.conf, определите директиву bind и активируйте режим кластера. Порты в данном случае будут варьироваться в диапазоне от 6379 до 6381.

# bind 127.0.0.1
protected-mode no
port 6379
pidfile /var/run/redis_6379.pid
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000

Для каждого узла в проектируемом кластере Redis требуется доступность не только определенного порта, но и порта выше 10000. На сервере 1 оба порта TCP 6379 и 16379 должны быть открыты. Убедитесь, что файрвол настроен корректно.

В c_slave.conf настройки будут аналогичны, кроме номера порта. Позднее для его настройки режима slave, соответствующего определенному узлу master, будет использоваться сценарий redis-trib.rb, а не директива slaveof.

# bind 127.00.1
protected-mode no
port 6381
pidfile /var/run/redis_6381.pid
cluster-enabled yes
cluster-config-file nodes-6381.conf
cluster-node-timeout 15000

Повторите процедуру для оставшихся двух серверов, определив порты для всех пар master-slave.

ServerMasterSlave
163796381
263806379
363816380

Запуск узлов Master и Slave

Подключитесь по SSH к серверу 1 и запустите оба экземпляра Redis:

redis-server redis-stable/a_master.conf
redis-server redis-stable/c_slave.conf

Для других двух серверов замените a_master.conf и c_slave.conf соответствующим конфигурационным файлом. Все узлы master будут запущены в режиме кластера.

Создание кластера с использованием встроенного скрипта Ruby

На этом этапе на каждом сервере запущены по два независимых узла master. Дальнейшая установка кластера происходит с помощью скрипта Ruby, который хранится в ~/redis-stable/src/, позволяет создать кластер и управлять им.

Если Ruby еще не установлен, установите его:

sudo apt install ruby

Установите пакет Redis для Ruby:

gem install redis

Чтобы запустить скрипт, перейдите в каталог, где находится исходный код Redis и выполните настройку серверов кластера, передав список пар ip:port серверов, которые будут играть роль master:

redis-stable/src/redis-trib.rb create ip.of.server1:6379 ip.of.server2:6380 ip.of.server3:6381

При успешной установке кластера вернется ответ:

>>>Creating cluster
>>>Performing hash slots allocation on 3 nodes...
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join.
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

Теперь мы можем получить все связанные с кластером узлы с помощью redis-cli. Флаг -c определяет соединение с кластером:

redis-cli -c -h ip.of.server1 -p 6379
ip.of.server1>CLUSTER NODES

Эта команда возвращает список узлов в кластере, идентифицированных по ID. Для выхода из интерфейса нажмите exit.

ip.of.server1>exit

Команды Redis не чувствительны к регистру. Однако для ясности, в данной инструкции мы их пишем заглавными буквами.

На данном этапе в кластере только 3 master-сервера, данные будут распределяться по кластеру, но не реплицироваться. Присоединим к каждому серверу master один сервер slave, чтобы обеспечить репликацию данных.

Добавление узлов Slave

Для добавления новых узлов в кластер опять воспользуемся утилитой redis-trib. Для присоединения сервера slave к master будем использовать команду:

./redis-trib.rb add-node --slave --master-id [master_id_c] ip.of.server1:6381 ip.of.server3:6381

В результате должен вернуться ответ:

>>> Adding node ip.of.server1:6381 to cluster ip.of.server3:6381
>>> Performing Cluster Check (using node ip.of.server3:6381)
M: [master_id_c] ip.of.server3:6381
   slots:10923-16383 (5461 slots) master
   0 additional replica(s)
M: [master_id_a] ip.of.server1:6379
   slots:0-5460 (5461 slots) master
   0 additional replica(s)
M: [master_id_b] ip.of.server2:6380
   slots:5461-10922 (5462 slots) master
   0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node ip.of.server1:6381 to make it join the cluster.
Waiting for the cluster to join...
>>> Configure node as replica of ip.of.server3:6381.

Повторите это действие для двух оставшихся узлов:

./redis-trib.rb add-node --slave --master-id [master_id_a] ip.of.server2:6379 ip.of.server1:6379

./redis-trib.rb add-node --slave --master-id [master_id_b] ip.of.server3:6380 ip.of.server2:6380

Распределение данных

Интерфейс командной строки Redis позволяет задать и просмотреть ключи с помощью SET и GET и других команд. Вы можете присоединиться к любому из узлов master и получить свойства кластера Redis.

redis-cli -c -h ip.of.server1 -p 6379

Используйте команду CLUSTER INFO для просмотра информации о состоянии кластера, например, его размер, хэш слоты, ошибки, если они есть.

ip.of.server1:6379>CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:8375
cluster_stats_messages_pong_sent:9028
cluster_stats_messages_meet_sent:1
cluster_stats_messages_sent:17404
cluster_stats_messages_ping_received:9022
cluster_stats_messages_pong_received:8376
cluster_stats_messages_meet_received:6
cluster_stats_messages_received:17404

Для проверки репликации master/slave используйте INFO replication, которая возвращает информацию об узлах slave.

ip.of.server1:6379>INFO replication
role:master
connected_slaves:1
slave0:ip=ip.of.server1,port=6381,state=online,offset=213355,lag=1
master_replid:cd2e27cba094f2e7ed38b0313dcd6a979ab29b7a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:213355
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:197313
repl_backlog_histlen:16043

Для проверки распределения данных можно установить несколько пар ключ-значение.

ip.of.server1:6379> SET John Adams
-> Redirected to slot [6852] located at ip.of.server2:6380
OK
ip.of.server2:6380> SET James Madison
-> Redirected to slot [2237] located at ip.of.server1:6379
OK
ip.of.server1:6379> SET Andrew Jackson
-> Redirected to slot [15768] located at ip.of.server3:6381
OK
ip.of.server3:6381> GET John
-> Redirected to slot [6852] located at ip.of.server2:6380
"Adams"
ip.of.server2:6380>

Поведение Slave при отказе Master

При использовании данной топологии, при отказе одного из серверов кластер будет полностью работоспособен — узел оставшийся без master-а узел slave станет master-ом.

Для проверки добавим пару ключ-значение:

ip.of.server1:6379> SET foo bar
-> Redirected to slot [12182] located at ip.of.server3:6381
OK
ip.of.server3:6381> GET foo
"bar"

Ключ foo добавлен в master на сервере 3 и скопирован в slave на сервере 1.

В случае, если сервер 3 станет недоступен, slave на сервере 1 станет master и кластер останется доступным.

ip.of.server1:6379> CLUSTER NODES
[slave_id_b] ip.of.server3:6380@16380 slave,fail [master_id_b] 1502722149010 1502722147000 6 connected
[slave_id_a] ip.of.server2:6379@16379 slave [master_id_a] 0 1502722242000 5 connected
[slave_id_c_promoted] ip.of.server1:6381@16381 master - 0 1502722241651 7 connected 10923-16383
[master_id_b] ip.of.server2:6380@16380 master - 0 1502722242654 2 connected 5461-10922
[master_id_c] ip.of.server3:6381@16381 master,fail - 1502722149010 1502722145402 3 connected
[master_id_a] ip.of.server1:6379@16379 myself,master - 0 1502722241000 1 connected 0-5460

Для ключа, который был в хэш слоте на сервере 3, пара ключ-значение теперь хранится на сервере 1.

ip.of.server1:6379> GET foo
-> Redirected to slot [12182] located at ip.of.server1:6381
"bar"

Дополнительная функциональность, например, добавление узлов, создание нескольких узлов slave, или resharding данных не описана в данном руководстве. Подробнее о том, как использовать эти возможности, читайте в официальной документации Redis.

Дополнительные ресурсы

Возможно, вам будут полезны ссылки ниже для получения более подробной информации по теме: