Два вида построения и простое использование Redis Cluster

Redis
Два вида построения и простое использование Redis Cluster

Redis Cluster — это официальное распределенное решение Redis с высокой доступностью. Всего в Redis Cluster 2^14 (16384) слотов, после создания кластера эти слоты необходимо равномерно распределить между каждым узлом.

подготовить узел

Конфигурация узла

Кластер Redis обычно состоит из нескольких узлов, и количество узлов составляет не менее 6, чтобы обеспечить полный и высокодоступный кластер. Планирование узла кластера Redis выглядит следующим образом:

имя узла Номер порта главный/подчиненный узел реплицированный узел
redis-6379 6379 главный узел ---
redis-6378 6378 главный узел ---
redis-6377 6377 главный узел ---
redis-6376 6376 подчиненный узел redis-6379
redis-6375 6375 подчиненный узел redis-6378
redis-6374 6374 подчиненный узел redis-6377

Рекомендуется унифицировать каталог для всех узлов в кластере.Как правило, он разделен на три каталога: conf, data и log, в которых соответственно хранятся файлы конфигурации, данных и журналов.

$ tree -L 2
.
├── conf
│   ├── redis-6374.conf
│   ├── redis-6375.conf
│   ├── redis-6376.conf
│   ├── redis-6377.conf
│   ├── redis-6378.conf
│   └── redis-6379.conf
├── data
│   ├── redis-6374
│   ├── redis-6375
│   ├── redis-6376
│   ├── redis-6377
│   ├── redis-6378
│   └── redis-6379
└── log
    ├── redis-6374.log
    ├── redis-6375.log
    ├── redis-6376.log
    ├── redis-6377.log
    ├── redis-6378.log
    └── redis-6379.log

9 directories, 12 files

Здесь просто скопируйте 6 копий redis.conf в каталог conf и измените его на конфигурацию, требуемую кластером. Создайте 6 новых папок под данными, соответствующих 6 узлам (названным именами узлов). Создайте 6 файлов журнала в журнале (также с именем узла).

Измените файл конфигурации следующим образом: это конфигурация redis-6379, остальные пять конфигураций аналогичны.

# redis后台运行
daemonize yes

# 数据存放目录
dir /usr/local/redis-cluster/data/redis-6379

# 日志文件
logfile /usr/local/redis-cluster/log/redis-6379.log

# 端口号
port 6379

# 开启集群模式
cluster-enabled yes

# 集群的配置,配置文件首次启动自动生成
# 这里只需指定文件名即可,集群启动成功后会自动在data目录下创建
cluster-config-file "nodes-6379.conf"

# 请求超时,设置10秒
cluster-node-timeout 10000

начальный узел

Запустите 6 узлов отдельно:

sudo redis-server conf/redis-6379.conf
sudo redis-server conf/redis-6378.conf
sudo redis-server conf/redis-6377.conf
sudo redis-server conf/redis-6376.conf
sudo redis-server conf/redis-6375.conf
sudo redis-server conf/redis-6374.conf

Посмотрите лог для redis-6379:

11003:C 02 Feb 2020 22:45:04.655 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
11003:C 02 Feb 2020 22:45:04.656 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=11003, just started
11003:C 02 Feb 2020 22:45:04.657 # Configuration loaded
11004:M 02 Feb 2020 22:45:04.674 * Increased maximum number of open files to 10032 (it was originally set to 1024).
11004:M 02 Feb 2020 22:45:04.679 * No cluster configuration found, I'm 7d480c106752e0ba4be3efaf6628bd7c8c124013
11004:M 02 Feb 2020 22:45:04.788 * Running mode=cluster, port=6379.
11004:M 02 Feb 2020 22:45:04.789 # Server initialized
11004:M 02 Feb 2020 22:45:04.790 * Ready to accept connections

Видно, что Redis запускается в режиме кластера, так как конфигурации кластера в начале нет, конфигурация создается автоматически (имя файла указано в redis-6379.conf).

Затем взгляните на автоматически созданную конфигурацию кластера. В этом файле записано начальное состояние кластера, а длинная строка впереди — это идентификатор узла.

7d480c106752e0ba4be3efaf6628bd7c8c124013 127.0.0.1:6379@16379 myself,master - 0 1580657311000 0 connected 
vars currentEpoch 5 lastVoteEpoch 0

Ручная сборка

Рукопожатие узла

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

Рукопожатие узла должно быть инициировано клиентом: кластер соответствует {ip} {port}, клиент может завершить рукопожатие всего кластера (рукопожатие фактически добавляет другой узел в кластер, после успешного рукопожатия состояние будет отправлено в кластер через следующее сообщение Распространение в середине, другие узлы автоматически обнаружат новый узел и инициируют рукопожатие, и, наконец, все узлы воспринимают друг друга и образуют кластер).

Войдите в клиент redis-6379, чтобы инициировать рукопожатие:

127.0.0.1:6379> cluster meet 127.0.0.1 6378
127.0.0.1:6379> cluster meet 127.0.0.1 6377
127.0.0.1:6379> cluster meet 127.0.0.1 6376
127.0.0.1:6379> cluster meet 127.0.0.1 6375
127.0.0.1:6379> cluster meet 127.0.0.1 6374

Просмотрите узлы кластера:

127.0.0.1:6379> cluster nodes
13793dee9c570fd88297fd406ecb9c6a83ab670d 127.0.0.1:6374@16374 master - 0 1580655577754 5 connected
7d480c106752e0ba4be3efaf6628bd7c8c124013 127.0.0.1:6379@16379 myself,master - 0 1580655577000 0 connected
359acf2a5134bdc0059464100ad712564062b731 127.0.0.1:6375@16375 master - 0 1580655576000 4 connected
2f2b41c194343fe88845fea5caa3796c50f71bbb 127.0.0.1:6378@16378 master - 0 1580655575000 1 connected
169fae6f05e58bd944057d5f814abefdd34eb4b2 127.0.0.1:6377@16377 master - 0 1580655576000 2 connected
3fe3f423e8ba0c289a71702a78ad44a585c4a0fe 127.0.0.1:6376@16376 master - 0 1580655576745 3 connected

Однако в настоящее время кластер нельзя использовать, так как узлу не был выделен слот, поэтому данные не могут быть прочитаны и записаны.
Вы можете просмотреть информацию о кластере (состояние кластера — отказ, а выделенный слот равен 0):

127.0.0.1:6379> cluster info
cluster_state:fail
cluster_slots_assigned:0
...

слот распределения

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

redis-cli -p 6379 cluster addslots {0..5461}
redis-cli -p 6378 cluster addslots {5462..10922}
redis-cli -p 6377 cluster addslots {10922..16383}

Разделите слоты 16384 поровну на 3 узла, а затем проверьте состояние кластера, вы можете обнаружить, что он стал ОК.

127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
...

Снова взглянув на слоты кластера, вы увидите диапазон слотов, выделенных каждому узлу, и информацию об узлах.

127.0.0.1:6379> cluster slots
1) 1) (integer) 0
   2) (integer) 5461
   3) 1) "127.0.0.1"
      2) (integer) 6379
      3) "7d480c106752e0ba4be3efaf6628bd7c8c124013"
2) 1) (integer) 5462
   2) (integer) 10922
   3) 1) "127.0.0.1"
      2) (integer) 6378
      3) "2f2b41c194343fe88845fea5caa3796c50f71bbb"
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "127.0.0.1"
      2) (integer) 6377
      3) "169fae6f05e58bd944057d5f814abefdd34eb4b2"

Мы запустили в общей сложности 6 узлов, но только 3 узла используются для выделения слотов здесь, а остальные 3 узла используются для репликации ведущий-ведомый, чтобы гарантировать, что аварийное переключение может быть выполнено, когда главный узел выходит из строя, а подчиненный узел отвечает за копирование информации о слоте главного узла и связанных данных. Вы можете использовать следующую команду, чтобы сделать узел подчиненным узлом (эта команда должна быть выполнена на клиенте подчиненного узла).

redis-cli -p 6376
127.0.0.1:6376> cluster replicate 7d480c106752e0ba4be3efaf6628bd7c8c124013(这个是6379节点的ID)
OK
127.0.0.1:6376> exit

redis-cli -p 6375
127.0.0.1:6375> cluster replicate 2f2b41c194343fe88845fea5caa3796c50f71bbb(这个是6378节点的ID)
OK
127.0.0.1:6375> exit

redis-cli -p 6374
127.0.0.1:6374> cluster replicate 169fae6f05e58bd944057d5f814abefdd34eb4b2(这个是6377节点的ID)
OK
127.0.0.1:6374> exit

На данный момент кластер Redis Cluster успешно построен. Наконец, давайте посмотрим на состояние узлов кластера (три ведущих и три подчиненных)

127.0.0.1:6379> cluster nodes
13793dee9c570fd88297fd406ecb9c6a83ab670d 127.0.0.1:6374@16374 slave 169fae6f05e58bd944057d5f814abefdd34eb4b2 0 1580657364167 5 connected
7d480c106752e0ba4be3efaf6628bd7c8c124013 127.0.0.1:6379@16379 myself,master - 0 1580657362000 0 connected 0-5461
359acf2a5134bdc0059464100ad712564062b731 127.0.0.1:6375@16375 slave 2f2b41c194343fe88845fea5caa3796c50f71bbb 0 1580657360000 4 connected
2f2b41c194343fe88845fea5caa3796c50f71bbb 127.0.0.1:6378@16378 master - 0 1580657363000 1 connected 5462-10922
169fae6f05e58bd944057d5f814abefdd34eb4b2 127.0.0.1:6377@16377 master - 0 1580657365175 2 connected 10923-16383
3fe3f423e8ba0c289a71702a78ad44a585c4a0fe 127.0.0.1:6376@16376 slave 7d480c106752e0ba4be3efaf6628bd7c8c124013 0 1580657363160 3 connected

Автоматическая сборка

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

Я использую Redis5.Если это более низкая версия, есть инструмент redis-trib.rb.При его использовании вам необходимо установить зависимость redis gem (gem install redisЕсли среды ruby ​​нет, сначала установите ruby).

Во-первых, остановите все узлы кластера, созданные выше вручную, и удалите все файлы в каталоге данных.
Если узел в предыдущем кластере сохранил данные или конфигурация кластера не была удалена, будет сообщено об аналогичной ошибке.[ERR] Node 127.0.0.1:6378 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.Если конфигурация кластера не удалена, удалите все конфигурации кластера, в противном случае введите клиент, который ранее сохранил данные для выполненияflushallиcluster resetСотрите данные и перезагрузите кластер.
Затем перезапустите все узлы. Просто введите следующее, чтобы создать кластер для Redis 5:

redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6378 127.0.0.1:6377 127.0.0.1:6376 127.0.0.1:6375 127.0.0.1:6374 --cluster-replicas 1

За create следуют адреса и порты 6 узлов, опция --cluster-replicas 1 означает предоставление подчиненного узла для каждого главного узла. Создайте результат следующим образом:

>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: 872e3876ea53a1ba1a77af3fb5a8c72704ac0eab 127.0.0.1:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: e80c00d029005bb132b08ddbdb4029a10feff839 127.0.0.1:6376
   slots: (0 slots) slave
   replicates a6651e15af616cfe720c7731f8748fffbde56822
M: a6651e15af616cfe720c7731f8748fffbde56822 127.0.0.1:6378
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 10e8962e8ce4b0200c3ee5ffcf03d196f72f72fc 127.0.0.1:6374
   slots: (0 slots) slave
   replicates 872e3876ea53a1ba1a77af3fb5a8c72704ac0eab
M: 74af8a6c3dce0420707e5253fdb0a2f0c039b1a3 127.0.0.1:6377
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: f96b0261c775cf10a254f28374a4ed73c2977b1b 127.0.0.1:6375
   slots: (0 slots) slave
   replicates 74af8a6c3dce0420707e5253fdb0a2f0c039b1a3
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

Простой в использовании

redis-cli с использованием кластера

Redis-cli добавляет -c для запуска в режиме коммутатора, который будет поддерживать использование кластеров.

$ redis-cli -c -p 6379
127.0.0.1:6379> set name cluster
-> Redirected to slot [5798] located at 127.0.0.1:6378
OK
127.0.0.1:6378> get name
"cluster"

Когда ключевая команда используется для установки значения имени в redis-6379, соответствующий слот — 5798, который принадлежит узлу redis-6378, поэтому режим переключения автоматически перенаправляется на узел redis-6378 для выполнения ключевой команды. .

перешлифовка

Решардинг — это фактически миграция слотов. Перенос хеш-слотов с одного или нескольких узлов на другой.
Redis официально предоставляет команды для решардинга, но если версия Redis ниже 5, все равно используется инструмент redis-trib.rb.

redis-cli --cluster reshard 127.0.0.1:6379

Здесь нужно указать только один узел, и redis-cli автоматически найдет другие узлы.
Сначала он проверит рабочее состояние кластера, а затем спросит, сколько слотов вы хотите перераспределить (здесь я указал 1000 слотов).How many slots do you want to move (from 1 to 16384)?
Затем нам нужно указать ID цели решардинга (то есть, какая нода получит эти переназначенные слоты).
Вы можете просмотреть информацию об узле (включая идентификатор узла) с помощью следующей команды.

redis-cli -p 6379 cluster nodes | grep myself
872e3876ea53a1ba1a77af3fb5a8c72704ac0eab 127.0.0.1:6379@16379 myself,master - 0 1580801413000 7 connected 0-5961 10923-11421

Наконец, вам нужно указать, из каких узлов получать слоты (здесь просто укажите все, то есть все узлы). Начинается перешардинг, и терминал видит, что слот перемещается с одного узла на другой.
Наконец, проверка состояния кластера показывает, что количество слотов целевого узла стало равным 6461.

redis-cli --cluster check 127.0.0.1:6379
127.0.0.1:6379 (872e3876...) -> 1 keys | 6461 slots | 1 slaves.
127.0.0.1:6378 (a6651e15...) -> 0 keys | 4961 slots | 1 slaves.
127.0.0.1:6377 (74af8a6c...) -> 0 keys | 4962 slots | 1 slaves.

отказоустойчивость

Проверка отказа

Давайте сначала посмотрим на узлы в текущем кластере:

redis-cli -a redis666 cluster nodes
872e3876ea53a1ba1a77af3fb5a8c72704ac0eab 127.0.0.1:6379@16379 myself,master - 0 1580823411000 7 connected 0-5961 10923-11421
74af8a6c3dce0420707e5253fdb0a2f0c039b1a3 127.0.0.1:6377@16377 slave f96b0261c775cf10a254f28374a4ed73c2977b1b 0 1580823412846 9 connected
e80c00d029005bb132b08ddbdb4029a10feff839 127.0.0.1:6376@16376 slave a6651e15af616cfe720c7731f8748fffbde56822 0 1580823411000 4 connected
f96b0261c775cf10a254f28374a4ed73c2977b1b 127.0.0.1:6375@16375 master - 0 1580823409820 9 connected 11422-16383
a6651e15af616cfe720c7731f8748fffbde56822 127.0.0.1:6378@16378 master - 0 1580823412000 2 connected 5962-10922
10e8962e8ce4b0200c3ee5ffcf03d196f72f72fc 127.0.0.1:6374@16374 slave 872e3876ea53a1ba1a77af3fb5a8c72704ac0eab 0 1580823410835 7 connected

Здесь команда debug segfault используется для сбоя главного узла 6378 (согласно приведенной выше информации мы видим, что подчиненным узлом redis-6378 является redis-6376).

redis-cli -p 6378 debug segfault

Затем подождите некоторое время, вы обнаружите, что отработка отказа была завершена автоматически, и redis-6376 стал новым главным узлом (redis-6378 находится в состоянии отказа):

e80c00d029005bb132b08ddbdb4029a10feff839 127.0.0.1:6376@16376 master - 0 1580823678628 10 connected 5962-10922
a6651e15af616cfe720c7731f8748fffbde56822 127.0.0.1:6378@16378 master,fail - 1580823551245 1580823549000 2 disconnected

Снова запустите redis-6378, и кластер снова присоединит его к кластеру и сделает его подчиненным узлом главного узла с наименьшим количеством подчиненных узлов (в данном случае redis-6376).

e80c00d029005bb132b08ddbdb4029a10feff839 127.0.0.1:6376@16376 master - 0 1580823829221 10 connected 5962-10922
a6651e15af616cfe720c7731f8748fffbde56822 127.0.0.1:6378@16378 slave e80c00d029005bb132b08ddbdb4029a10feff839 0 1580823830226 10 connected

Ручной переход на другой ресурс

Введите любой подчиненный узел (только подчиненный узел) и выполнитеcluster failoverВыполните аварийное переключение вручную (ручное аварийное переключение просто меняет отношения между ведущим и подчиненным).
Здесь выполняется ручной отказоустойчивость redis-6374 и выполняется состояние предыдущего узла (redis-6374 — подчиненный узел, а redis-6379 — главный узел).

10e8962e8ce4b0200c3ee5ffcf03d196f72f72fc 127.0.0.1:6374@16374 myself,slave 872e3876ea53a1ba1a77af3fb5a8c72704ac0eab 0 1580825791000 6 connected
872e3876ea53a1ba1a77af3fb5a8c72704ac0eab 127.0.0.1:6379@16379 master - 0 1580825792000 7 connected 789-5961 10923-11421

Состояние после выполнения (redis-6374 — главный узел, redis-6379 — подчиненный узел)

10e8962e8ce4b0200c3ee5ffcf03d196f72f72fc 127.0.0.1:6374@16374 myself,master - 0 1580825812000 12 connected 789-5961 10923-11421
872e3876ea53a1ba1a77af3fb5a8c72704ac0eab 127.0.0.1:6379@16379 slave 10e8962e8ce4b0200c3ee5ffcf03d196f72f72fc 0 1580825813000 12 connected

добавить/удалить узлы

добавить узел

Согласно предыдущей конфигурации добавьте новый узел redis-6373, а затем запустите его. Присоедините его к кластеру с помощью следующей команды.

# 127.0.0.1:6373指的是新加入集群中的节点的ip和端口
# 127.0.0.1:6379指的是集群中的某个节点的ip和地址(随便哪个节点都行)
redis-cli --cluster add-node 127.0.0.1:6373 127.0.0.1:6379

По сути, функция этой команды такая же, как и у clustermeet, то есть она используется для установления связи узлов (разница только в том, что перед выполнением будет проверяться состояние кластера).
Помните, что когда вы ранее создавали кластер вручную, вам нужно было назначить слот узлу после завершения рукопожатия узла. Так как 16384 слота здесь были выделены, повторное разделение используется здесь для выделения слотов новым узлам (новый узел является целевым узлом для повторного разделения).
После повторного разделения взгляните на слоты, за которые отвечает новый узел (все узлы имеют 1999 слотов, выделенных новому узлу, и можно обнаружить, что слоты нового узла имеют три диапазона).

M: 533168c99a03b5593408818dabc1db36396a221f 127.0.0.1:6373
   slots:[0-788],[5962-6566],[11422-12026] (1999 slots) master

удалить узел

Чтобы удалить подчиненный узел, просто используйте команду del-node:

# 127.0.0.1:6379是集群中的任意一个节点Ip和端口
# node-id就是要删除的节点ID
redis-cli --cluster del-node 127.0.0.1:6379 <node-id>

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

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

redis-cli --cluster reshard 127.0.0.1:6374

...

How many slots do you want to move (from 1 to 16384)? 1999
What is the receiving node ID?
f96b0261c775cf10a254f28374a4ed73c2977b1b # 目标节点redis-6375的ID
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: 533168c99a03b5593408818dabc1db36396a221f # 源节点redis-6373的ID
Source node #2: done # 只有一个源节点,输入done结束

Проверьте состояние кластера после миграции, вы можете обнаружить, что слот узла redis-6373 равен 0, и тогда вы можете смело удалить узел.

redis-cli --cluster check 127.0.0.1:6375
127.0.0.1:6375 (f96b0261...) -> 0 keys | 6356 slots | 1 slaves.
127.0.0.1:6374 (10e8962e...) -> 1 keys | 5672 slots | 1 slaves.
127.0.0.1:6373 (533168c9...) -> 0 keys | 0 slots | 0 slaves.
127.0.0.1:6376 (e80c00d0...) -> 0 keys | 4356 slots | 1 slaves.

Безопасно удалите узел redis-6373 из кластера (из журнала можно узнать, что redis вызывает кластер, забыв сначала забыть узел, а затем переводит узел в автономный режим)

redis-cli --cluster del-node 127.0.0.1:6375 533168c99a03b5593408818dabc1db36396a221f
>>> Removing node 533168c99a03b5593408818dabc1db36396a221f from cluster 127.0.0.1:6375
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.

Снова взглянув на узлы кластера, можно обнаружить, что узла redis-6373 больше нет.

redis-cli cluster nodes
f96b0261c775cf10a254f28374a4ed73c2977b1b 127.0.0.1:6375@16375 master - 0 1580965689000 13 connected 0-788 5962-6566 11422-16383
e80c00d029005bb132b08ddbdb4029a10feff839 127.0.0.1:6376@16376 master - 0 1580965690554 10 connected 6567-10922
a6651e15af616cfe720c7731f8748fffbde56822 127.0.0.1:6378@16378 slave e80c00d029005bb132b08ddbdb4029a10feff839 0 1580965685000 10 connected
74af8a6c3dce0420707e5253fdb0a2f0c039b1a3 127.0.0.1:6377@16377 slave f96b0261c775cf10a254f28374a4ed73c2977b1b 0 1580965688000 13 connected
872e3876ea53a1ba1a77af3fb5a8c72704ac0eab 127.0.0.1:6379@16379 myself,slave 10e8962e8ce4b0200c3ee5ffcf03d196f72f72fc 0 1580965686000 12 connected
10e8962e8ce4b0200c3ee5ffcf03d196f72f72fc 127.0.0.1:6374@16374 master - 0 1580965689549 12 connected 789-5961 10923-11421