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();
}
}