Создание кластера Redis (5.0)

Redis

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

1、主从复制

2、哨兵模式

3、Redis官方提供的Cluster集群模式(服务端)

4、Jedis sharding集群(客户端sharding)

5、利用中间件代理,比如豌豆荚的codis等

2. Кратко разберем принцип, плюсы и минусы

2.1 Репликация Master-Slave:

Принцип репликации master-slave:

  • Подчиненный сервер подключается к главному серверу и отправляет команду SYNC;

  • После того, как главный сервер получает имя SYNC, он начинает выполнять команду BGSAVE для создания файла RDB и использует буфер для записи всех команд записи, выполняемых после этого;

  • После того, как главный сервер BGSAVE выполнен, он отправляет файлы моментальных снимков на все подчиненные серверы и продолжает записывать выполненные команды записи в течение периода отправки;

  • После получения файла снимка с сервера отбросить все старые данные и загрузить полученный снимок;

  • После того, как снапшот главного сервера отправлен, он начинает посылать команду записи в буфер подчиненному серверу;

  • Подчиненный сервер завершает загрузку моментального снимка, начинает получать запросы команд и выполняет команду записи из буфера главного сервера; (инициализация подчиненного сервера завершается)

  • Каждый раз, когда главный сервер выполняет команду записи, он отправляет эту же команду записи подчиненному серверу, а подчиненный сервер получает и выполняет полученную команду записи (операция после инициализации подчиненного сервера).

  • Мастер может иметь несколько ведомых, но ведомый может соответствовать только одному ведущему.

преимущество:

  • Поддерживает репликацию master-slave, хост автоматически синхронизирует данные с ведомым устройством, а также может быть выполнено разделение чтения и записи.
  • Для того, чтобы разгрузить ведущее устройство от операций чтения, ведомый сервер может предоставлять клиенту операции только для чтения, а служба записи все равно должна выполняться главным узлом.
  • Ведомые устройства также могут принимать запросы на подключение и синхронизацию от других ведомых устройств, что может эффективно снять нагрузку синхронизации со стороны ведущего устройства.
  • Главный сервер обслуживает подчиненные без блокировки. Таким образом, во время синхронизации Master-Slave клиенты по-прежнему могут отправлять запросы или изменять запросы.
  • Ведомый сервер также выполняет неблокирующую синхронизацию данных. Во время синхронизации, если клиент отправляет запрос на запрос, Redis возвращает данные перед синхронизацией.

недостаток:

  • Redis не имеет функций автоматической отказоустойчивости и восстановления. Время простоя хоста и подчиненного устройства приведет к сбою некоторых запросов на чтение и запись во внешнем интерфейсе. Необходимо дождаться перезагрузки машины или вручную переключить внешний IP-адрес. выздороветь.
  • Когда хост не работает, некоторые данные не могут быть синхронизированы с подчиненным до времени простоя.После переключения IP возникает проблема несогласованности данных, что снижает доступность системы.
  • Redis сложно поддерживать онлайн-расширение, а онлайн-расширение становится очень сложным, когда емкость кластера достигает верхнего предела.

2.2. Дозорный режим:

Когда первичный сервер выходит из строя, вторичный сервер может быть обновлен до первичного сервера, чтобы продолжать предоставлять услуги, но этот процесс требует ручных операций. С этой целью в Redis 2.8 предусмотрен инструмент Sentinel для автоматизации мониторинга системы и восстановления после сбоев.

Роль часового заключается в отслеживании рабочего состояния системы Redis. В его функции входят следующие две.

(1)监控主服务器和从服务器是否正常运行。 
(2)主服务器出现故障时自动将从服务器转换为主服务器。

Как работает Сентинел:

  • Каждый процесс Sentinel (Сентинел) отправляет команду PING на Главный главный сервер, Слейв-подчиненный сервер и другие процессы Sentinel (Сентинел) во всем кластере с частотой один раз в секунду.
  • Если экземпляр (экземпляр) превышает значение, указанное параметром down-after-milliseconds из последнего действительного ответа на команду PING, экземпляр будет помечен процессом Sentinel как субъективно отключенный (SDOWN).
  • Если главный главный сервер помечен как субъективно отключенный (SDOWN), все процессы Sentinel, отслеживающие главный главный сервер, должны подтверждать, что главный главный сервер действительно перешел в субъективное автономное состояние с частотой один раз в секунду.
  • Когда достаточное количество процессов Sentinel (sentry) (большее или равное значению, указанному в файле конфигурации) подтвердит, что главный главный сервер перешел в субъективное автономное состояние (SDOWN) в течение указанного диапазона времени, главный главный сервер быть помеченным как цель в автономном режиме (ODOWN)
  • Как правило, каждый процесс Sentinel будет отправлять команды INFO всем основным главным серверам и подчиненным подчиненным серверам в кластере каждые 10 секунд.
  • Когда главный главный сервер помечен процессом Sentinel (сторожевым) как объектный в автономном режиме (ODOWN), частота отправки команд INFO всем подчиненным серверам главного главного сервера процесса часового (сторожевого) изменится с одного раза каждые 10 секунд. к каждой каждой секунде.
  • Если процессов Sentinel недостаточно, чтобы согласиться на отключение главного главного сервера, объективный статус главного главного сервера в автономном режиме будет удален. Если главный главный сервер повторно отправляет команду PING процессу Sentinel и возвращает действительный ответ, субъективный статус главного главного сервера в автономном режиме будет удален.

преимущество:

  • Режим Sentinel основан на режиме ведущий-ведомый, и все преимущества режима ведущий-ведомый доступны в режиме Sentinel.
  • Мастер-ведомый может переключаться автоматически, система более надежна, а доступность выше.

недостаток:

  • Redis сложно поддерживать онлайн-расширение, а онлайн-расширение становится очень сложным, когда емкость кластера достигает верхнего предела.

2.3, официальный кластерный режим Redis Cluster

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

Redis-Cluster использует бесцентровую структуру со следующими характеристиками:

  • Все узлы redis взаимосвязаны друг с другом (механизм PING-PONG), а внутренний бинарный протокол используется для оптимизации скорости передачи и пропускной способности.

  • Сбой узла вступает в силу только тогда, когда более половины узлов в кластере обнаруживают сбой.

  • Клиент напрямую подключается к узлу redis и не требует промежуточного уровня прокси.Клиенту не нужно подключаться ко всем узлам в кластере, достаточно подключиться к любому доступному узлу в кластере.

Способ работы:

На каждом узле Redis есть две вещи, одна из них — слот, и ее диапазон значений: 0-16383. Другой — кластер, который можно понимать как плагин для управления кластером. Когда наш ключ доступа прибудет, redis получит результат в соответствии с алгоритмом crc16, а затем рассчитает остаток результата до 16384, так что каждый ключ будет соответствовать хеш-слоту с номером от 0 до 16383, через это значение, чтобы найти узел, соответствующий соответствующему слоту, а затем автоматически перейти непосредственно к соответствующему узлу для операций доступа.

Чтобы обеспечить высокую доступность, кластер redis-cluster вводит режим ведущий-ведомый.Главный узел соответствует одному или нескольким подчиненным узлам.Когда главный узел выходит из строя, подчиненный узел включается. Когда другие главные узлы пингуют главный узел A, если более половины главных узлов взаимодействуют с A сверхурочно, то главный узел A считается отключенным.Если главный узел A и подчиненный ему узел A1 не работают, кластер больше не может предоставлять услуги.

2.4, шардинговый кластер Jedis

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

К счастью, клиентский драйвер Java Redis Jedis уже поддерживает функцию Redis Sharding, а именно ShardedJedis и ShardedJedisPool в сочетании с пулом кеша.

Реализация Redis Sharding Jedis имеет следующие характеристики:

  • Алгоритм согласованного хеширования используется для одновременного хеширования ключа и имени узла, а затем сопоставления и сопоставления.Используемый алгоритм — MURMUR_HASH. Основная причина использования последовательного хеширования вместо простого хеш-подобного отображения по модулю заключается в том, что при добавлении или удалении узлов повторного хеширования не происходит из-за повторного сопоставления. Согласованное хеширование влияет только на распределение ключей соседних узлов, и степень влияния невелика.
  • Во избежание последовательного хеширования, влияющего только на соседние узлы и вызывающего давление при распределении узлов, ShardedJedis будет виртуализировать 160 виртуальных узлов для хэширования для каждого узла Redis в соответствии с его именем (нет, Jedis предоставит имя по умолчанию). В зависимости от веса также могут быть виртуализированы виртуальные узлы, кратные 160. Использование виртуальных узлов для сопоставления сопоставлений может привести к более равномерному перемещению и перераспределению ключей между узлами Redis при добавлении или уменьшении узлов Redis, а не только к соседним узлам.
  • ShardedJedis поддерживает режим keyTagPattern, то есть извлечение части keyTag для шардинга, чтобы группу связанных ключей можно было поместить в один и тот же узел Redis, правильно назвав ключи, что очень важно при избежании межузлового доступа к связанным данные. Конечно, легкий и гибкий метод Redis Sharding должен идти на компромиссы в отношении других возможностей кластера. Например, если вы хотите увеличить количество узлов Redis, даже если вы используете согласованное хеширование, все равно будут ключи, которые не совпадают и потеряны.В этом случае требуется миграция значения ключа. В качестве упрощенного сегментирования на стороне клиента нереально обрабатывать миграцию ключ-значение Redis, которая требует, чтобы прикладной уровень допускал потерю данных в Redis или перезагружал данные из серверной базы данных. Но иногда разбивка уровня кэша и прямой доступ к уровню базы данных оказывает сильное давление на доступ к системе.

2.5 Использование промежуточного прокси Роль промежуточного программного обеспечения заключается в вычислении значения ключа данных, которые нам нужно хранить в Redis, с помощью набора алгоритмов. Затем найдите соответствующий узел redis в соответствии с этим значением и сохраните данные в узле redis.

Обычно используемое промежуточное ПО это

  • Twemproxy
  • Codis
  • nginx

3. У меня есть понимание нескольких режимов кластера, теперь построим кластер

Так как я использовал redis5.0, то в процессе сборки тоже столкнулся с ямой.Redis5.0 использует redis-cli в качестве команды для создания кластера, которая реализована на языке C вместо языка ruby.Redis3.0 использует redis -trib.rb Для создания кластера необходимо установить ruby.

Среда gcc была установлена ​​раньше, и теперь с ней не нужно разбираться, просто переходим к следующему шагу. 3.1 Скопируйте ранее установленный файл redis в новую папку redis-cluster и скопируйте его в 6 копий в новую папку.

Будьте внимательны и удаляйте постоянные файлы с суффиксами .rdb и .aof, если таковые имеются.

Я не буду здесь рассматривать метод построения 3.0.

3.2 Измените файл конфигурации redis.conf шести узлов следующим образом.

Если это один и тот же хост, порт должен быть другим. Разные хосты могут быть одинаковыми. Я использую здесь тот же хост, порт: 7001-7006.

daemonize yes

port **** #配置自己的节点端口

cluster-enabled yes # 开启集群

3.3 Сценарии запуска и завершения работы

Запустить скрипт:

cd redis1
./src/redis-server redis.conf
cd ..
cd redis2
./src/redis-server redis.conf
cd ..
cd redis3
./src/redis-server redis.conf
cd ..
cd redis4
./src/redis-server redis.conf
cd ..
cd redis5
./src/redis-server redis.conf
cd ..
cd redis6
./src/redis-server redis.conf
cd ..

Закройте скрипт:


./redis1/redis-cli -p 7001 shutdown
./redis1/redis-cli -p 7002 shutdown
./redis1/redis-cli -p 7003 shutdown
./redis1/redis-cli -p 7004 shutdown
./redis1/redis-cli -p 7005 shutdown
./redis1/redis-cli -p 7006 shutdown

3.4. Изменить разрешения

chmod 777 start-all.sh stop-all.sh

3.5, запустите узел

./start-all.sh

# 查看redis进程
ps -aux | grep redis

3.6, создайте кластер

redis-cli --cluster create  192.0.0.179:7001 192.0.0.179:7002 192.0.0.179:7003 192.0.0.179:7004 192.0.0.179:7005 192.0.0.179:7006 --cluster-replicas 1

Видно, что 6 узлов распределены по 3 ведущим узлам и 3 подчиненным узлам.

3.7 Запросить информацию о кластере

После успешного создания кластера войдите в любой узел Redis, чтобы запросить состояние узла в кластере.

Клиент входит в систему как кластер:

redis-cli -c -h 192.0.0.179 -p 7001
#其中-c表示以集群方式连接redis,-h指定ip地址,-p指定端口号

Запрос информации об узле кластера:

cluster nodes

3.8 Тест

192.0.0.179:7001> set a 123456
-> Redirected to slot [15495] located at 192.0.0.179:7003
OK
192.0.0.179:7003> get a
"123456"
192.0.0.179:7003> get a
"123456"
192.0.0.179:7003> set b 44444444
-> Redirected to slot [3300] located at 192.0.0.179:7001
OK
192.0.0.179:7001> get b
"44444444"
192.0.0.179:7001> 

Видно, что кластер redis выделит нам хеш-слоты в соответствии с расчетом для выделения разных узлов.

3.9, используйте соединение jedis

package com.pc.jedis.test;
 
import java.util.HashSet;
import java.util.Set;
 
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
 

public class JedisClusterTest {
    public static void main(String[] args) {
        // 创建并填充节点信息
        Set<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.0.0.179", 7001));
        nodes.add(new HostAndPort("192.0.0.179", 7002));
        nodes.add(new HostAndPort("192.0.0.179", 7003));
        nodes.add(new HostAndPort("192.0.0.179", 7004));
        nodes.add(new HostAndPort("192.0.0.179", 7005));
        nodes.add(new HostAndPort("192.0.0.179", 7006));
 
        // 创建JedisCluster对象
        JedisCluster jedisCluster = new JedisCluster(nodes);
 
        // 使用jedisCluster操作redis
        String key = "clusterTest";
        String setResult = jedisCluster.set(key, "redis集群搭建");
        System.out.println(setResult);
 
        String getResult = jedisCluster.get(key);
        System.out.println(getResult);
 
        // 关闭jedisCluster(程序执行完后才能关闭,内部封装了连接池)
        jedisCluster.close();
    }
}