Redis кластер живой провал сбой - PullRequest
0 голосов
/ 31 октября 2018

Мы широко используем redis-cluster в нашей производственной среде. В настоящее время у нас есть 30 узлов кластера (15 мастеров, 15 рабов) Мы пытаемся увеличить кластер, для этого мы создали новые серверы и присоединили их к кластеру. пока все хорошо.

Далее - мы пытаемся передать слоты новым мастерам. мы написали скрипт, который делает это, используя команду redis-trib reshard.

Однако - миграция не выполняется на полпути (но не очень далеко от начала) с этой ошибкой: [ERR] Calling MIGRATE: ERR Target instance replied with error: BUSYKEY Target key name already exists.

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

Мы не нашли ни конкретного примера этого, ни идеи о том, как предотвратить это, кроме простоя миграции. которого мы пытаемся избежать.

Версия:
Redis Server 4.0.2
Redis Trib 3.3.3 (понижено с 4.0.2 после этой проблемы: Redis кластера Reshard [ERR] Вызов MIGRATE: ERR Синтаксическая ошибка )

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

Надеемся услышать, что мы делаем что-то не так и как это исправить, или redis-cluster не создан для живого реширинга?

Спасибо

1 Ответ

0 голосов
/ 01 ноября 2018

Я сталкивался с такой проблемой при работе с поддержкой redis-clustering для нашего собственного проекта. Я обнаружил проблему с командой redis-trib reshard. Он работает нормально, если в слотах, которые мигрируют с одного мастера на другой, нет ключей.

Но у redis-5 (все еще развивающегося, еще не стабильного) есть свой 'redis-cli', у которого нет проблем с переносом команд, я думаю. Только для младших версий 5 это происходит.

Если вы посмотрите на официальные документы для redis, скажем, redisconfiguration и redis cluster reharding , вы найдете то, что они делают внутренне для повторной передачи.

Поэтому я решил эту проблему, выполнив эти задачи, запустив сценарий bash вместо команды redis-trib reshard.

Предположим, вы хотите переназначить некоторые слоты от главного узла к другому главному узлу. Мы назовем узел с текущим владельцем хеш-слота исходный узел , а узел, на который мы хотим перенести целевой узел .

Для каждого слота выполните следующие шаги:

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

  1. Отправьте CLUSTER SETSLOT <slot> IMPORTING <source-node-id> на узел назначения , чтобы установить слот на , импортируя состояние.
  2. Отправьте CLUSTER SETSLOT <slot> MIGRATING <destination-node-id> на исходный узел , чтобы установить слот в мигрирующее состояние.
  3. Получите ключи из исходного узла с помощью команды CLUSTER GETKEYSINSLOT и переместите их в целевой узел , используя следующую команду MIGRATE команда.

    MIGRATE target_host target_port key target_database_id timeout

    В Redis Cluster нет необходимости указывать базу данных, отличную от 0, но MIGRATE - это общая команда, которая может использоваться для других задач, не связанных с Redis Cluster.

  4. Когда процесс миграции окончательно завершится, используйте CLUSTER SETSLOT <slot> NODE <destination-node-id> в обоих исходных узлах и целевых узлах , чтобы снова установить для слота их нормальное состояние. Эта же команда обычно отправляется всем остальным узлам, чтобы избежать ожидания естественного распространения новой конфигурации по кластеру.

Простой пример сценария bash для этого также приведен здесь:

source-ip: 172.17.0.5. идентификатор источника: 1f70a5107e0042a7d33a9efaf88dbdfecd78076a

IP-адрес назначения: 172.17.0.4. ИД назначения: 7e428bae84697a3882ecad19bd0d13ac7ee97d02

другой мастер ip: 172.17.0.7

for i in `seq 0 5460`; do
    redis-cli -c -h 172.17.0.4 cluster setslot ${i} importing 1f70a5107e0042a7d33a9efaf88dbdfecd78076a
    redis-cli -c -h 172.17.0.5 cluster setslot ${i} migrating 7e428bae84697a3882ecad19bd0d13ac7ee97d02
    while true; do
        key=`redis-cli -c -h 172.17.0.5 cluster getkeysinslot ${i} 1`
        if [ "" = "$key" ]; then
            echo "there are no key in this slot ${i}"
            break
        fi
        redis-cli -h 172.17.0.5 migrate 172.17.0.4 6379 ${key} 0 5000
    done
    redis-cli -c -h 172.17.0.5 cluster setslot ${i} node 7e428bae84697a3882ecad19bd0d13ac7ee97d02
    redis-cli -c -h 172.17.0.4 cluster setslot ${i} node 7e428bae84697a3882ecad19bd0d13ac7ee97d02
    redis-cli -c -h 172.17.0.7 cluster setslot ${i} node 7e428bae84697a3882ecad19bd0d13ac7ee97d02
done
...