Redis — это типичная NoSQL база данных.
официальный сайт Redis: https://redis.io/download> Redis — это открытая система хранения данных типа key-value.
Подобно Memcached, она поддерживает больше типов значений, включая строка, список, множество, отсортированное множество, хэш.
Эти данные поддерживают операции push/pop, add/remove, а также операции с пересечением, объединением и вычитанием множеств, а также более сложные операции, которые являются атомарными.
Кроме того, Redis поддерживает различные способы сортировки.
Как и в случае с memcached, чтобы обеспечить эффективность, данные хранятся в оперативной памяти.
Отличие заключается в том, что Redis периодически записывает обновленные данные на диск или регистрирует изменения в виде последовательных записей.
На этой основе реализовано master-slave (мастер-слейв) синхронизацию.
Однопоточная модель + IO многоканальное использование. > Установите среду компиляции для языка C
yum install centos-release-scl scl-utils-build yum install -y devtoolset-8-toolchain scl enable devtoolset-8 bashИспользуйте wget для загрузки
wget https://download.redis.io/releases/redis-6.2.6.tar.gz // Путь загрузки: /optРаспакуйте архив в текущую директорию
tar -zxvf redis-6.2.6.tar.gz
После распаковки перейдите в директорию
cd redis-6.2.6
Выполните команду make в текущей директории
make && make install
По умолчанию установлено в
/usr/local/bin
```markdown
Решение проблем с CPU и памятью
Решение проблем с вводом-выводом (IO)
NoSQL (NoSQL = Not Only SQL), что означает "не только SQL", относится к нереляционным базам данных.
NoSQL не зависит от бизнес-логики при хранении данных, а использует простое ключ-значение (key-value) представление. Это значительно увеличивает возможности расширения базы данных.
Подходящие сценарии
Неподходящие сценарии
Основные NoSQL базы данных
Типы баз данных в эпоху больших данных
Строковые базы данных
Колоночные базы данных
redis.conf
Различие между верхним и нижним регистром не имеет значения.
Включение, в случае множественных экземпляров, можно выделить общие конфигурационные файлы.
## Сеть> Настройки сети.
По умолчанию bind=127.0.0.1
принимает запросы только с локальной машины.
Если значение не указано, то Redis принимает запросы с любых IP-адресов.
В продакшне обязательно указывайте адрес вашего сервера приложений, так как серверу требуется удалённый доступ, поэтому эту строку следует раскомментировать.
Если включен режим protected-mode, то Redis будет принимать запросы только с локальной машины, если не указан адрес bind ip и не задан пароль.
Установите режим защиты локального доступа на no.
Номер порта, по умолчанию 6379.
Устанавливает backlog для TCP, где backlog представляет собой очередь соединений, сумма которой равна сумме очередей, не завершившихся трёхсторонним рукопожатием, и завершившихся.
В условиях высокой конкуренции вам потребуется высокое значение backlog для предотвращения проблем с медленными клиентами.
Количество секунд, в течение которых Redis будет поддерживать пустой клиентский соединение перед его закрытием, 0 означает отключение этой функции, то есть никогда не закрывать.
tcp-keepalive
Периодическая проверка соединений с клиентами каждые n секунд.
Единица измерения — секунды; если значение равно 0, то проверка Keepalive не производится. Рекомендуется установить значение в 60.
daemonize
Установите в yes для запуска в фоновом режиме.
Демонизация, запуск в фоновом режиме.
![]()
pidfile
Путь к файлу с идентификатором процесса (PID). Каждый экземпляр создаёт свой уникальный PID-файл.
![]()
loglevel
Уровень логирования. Redis поддерживает четыре уровня: debug, verbose, notice, warning. По умолчанию установлено значение notice.
![]()
logfile
Имя файла лога.
![]()
database
Количество баз данных, по умолчанию 16. По умолчанию используется база данных 0. Можно использовать команду
SELECT <dbid>
для выбора базы данных по её ID.![]()
Просмотр, установка и удаление пароля доступа.
Установка пароля через команду временная. После перезапуска сервера redis пароль будет сброшен.
Для постоянной установки пароля необходимо указать его в конфигурационном файле.
Ограничение.
maxclients
Устанавливает количество одновременно подключаемых клиентов к redis.
По умолчанию это значение равно 10000.
При достижении этого ограничения, redis отклоняет новые запросы на подключение и отправляет ответ с сообщением max number of clients reached.
maxmemory
Обязательно следует установить, в противном случае заполнение памяти может привести к аварийному завершению работы сервера.
Устанавливает объем используемой памяти для redis. Как только достигается верхний предел использования памяти, redis попытается удалить внутренние данные, правила удаления можно указать через maxmemory-policy.
Если redis не может удалить данные согласно установленным правилам или если удаление запрещено, то redis вернет ошибку для команд, требующих выделения памяти, таких как SET, LPUSH и т. д.
Однако для команд, не требующих выделения памяти, таких как GET, ответ будет нормальным.Если ваш Redis является основным сервером (то есть у вас есть slave-серверы), то при установке предела использования памяти следует оставить некоторое пространство для буферизации синхронизации. Этот фактор следует учитывать только в том случае, если удаление запрещено.
maxmemory-policy
volatile-lru: Удаление ключей с использованием алгоритма LRU, но только для ключей с истечением срока действия (наиболее недавно использованных).
allkeys-lru: Удаление ключей с использованием алгоритма LRU для всех ключей.
volatile-random: Случайное удаление ключей из множества ключей с истечением срока действия.
allkeys-random: Случайное удаление ключей из всех ключей.
volatile-ttl: Удаление ключей с наименьшим значением TTL (те ключи, которые скоро истекут).
noeviction: Отказ от удаления. Для операций записи возвращается сообщение об ошибке.
maxmemory-samples: Установите количество образцов. Алгоритмы LRU и минимального TTL не являются точными алгоритмами, а представляют собой приближенные значения. Поэтому вы можете установить размер выборки, и по умолчанию Redis будет проверять указанное количество ключей и выбирать тот, который соответствует LRU.> Обычно рекомендуется использовать значения от 3 до 7. Чем меньше значение, тем менее точна выборка, но тем меньше затрат по производительности.
keys *
: просмотреть все ключи в текущей базе данных
exists key
: проверить наличие ключа
type key
: определить тип ключа
del key
: удалить указанный ключ
unlink key
: немедленное удаление ключа без блокировки, фактическое удаление происходит асинхронно
expire key 10
: установить время жизни для ключа
ttl key
: получить количество секунд до истечения времени жизни ключа, -1 означает, что ключ никогда не истекает, -2 означает, что ключ уже истек
select
: команда для смены базы данных
dbsize
: получить количество ключей в текущей базе данных
flushdb
: очистить текущую базу данных
flushall
: очистить все базы данных
Тип данных String является двоичной безопасностью. Это означает, что строки Redis могут содержать любые данные, такие как JPG изображения или сериализованные объекты.
Тип данных String является одним из самых базовых типов данных Redis. Максимальная длина значения строки может достигать 512 МБ.> set <ключ> <значение>
: добавить пару ключ-значение
get <ключ>
: получить значение по ключу
append <ключ> <значение>
: добавить значение в конец существующего значения
strlen <ключ>
: получить длину значения
setnx <ключ> <значение>
: установить значение ключа только если он ещё не существует
incr <ключ>
: увеличить значение ключа на 1, работает только со строками чисел, если ключ отсутствует, значение будет установлено в 1 (атомарная операция)
decr <ключ>
: уменьшить значение ключа на 1, работает только со строками чисел, если ключ отсутствует, значение будет установлено в -1
incrby/decrby <ключ> <шаг>
: увеличить/уменьшить значение ключа на заданный шаг
mset <ключ1> <значение1> <ключ2> <значение2>
: одновременно установить несколько пар ключ-значение
mget <ключ1> <ключ2> <ключ3>
: одновременно получить значения нескольких ключей
msetnx <ключ1> <значение1> <ключ2> <значение2>
: одновременно установить несколько пар ключ-значение, только если все ключи ещё не существуют
getrange <ключ> <начальная позиция> <конечная позиция>
: получить часть значения
setrange <ключ> <начальная позиция> <значение>
: заменить часть значения ключа
setex <ключ> <время жизни> <значение>
: установить значение ключа и время его жизни
getset <ключ> <значение>
: установить новое значение ключа и вернуть старое значениеАтомарностьАтомарной операцией называется такая операция, которая не может быть прервана потоковым расписанием;
такая операция начинается и завершается полностью без какого-либо переключения контекста (переключение на другой поток).
В однопоточной среде любая операция, которую можно выполнить в одной команде, считается атомарной операцией, поскольку прерывания могут произойти только между командами.
В многопоточной среде операция, которая не может быть прервана другими процессами (потоками), называется атомарной операцией.
Redis обеспечивает атомарность одиночных команд главным образом благодаря однопоточному исполнению Redis.
Данные и структура
Внутренняя реализация структуры данных аналогична Java's ArrayList, использует зарезервированное пространство для сокращения частых выделений памяти.
Список Redis представляет собой простую последовательность строк, отсортированную по порядку вставки. Вы можете добавить элемент в начало (слева) или конец (справа) списка.
На самом деле это двунаправленный связный список, что обеспечивает высокую производительность для операций с концами списка. Операции со средними элементами имеют меньшую производительность.
lpush/rpush <ключ><значение1><значение2><значение3> ...
: Вставка одного или нескольких значений слева/справа.lpush k1 v1 v2 v3 lrange k1 0 -1 вывод: v3 v2 v1 rpush k1 v1 v2 v3 rrange k1 0 -1 вывод: v1 v2 v3
lpop/rpop <ключ>
: Извлечение одного значения слева/справа. Если значение существует, ключ существует; если значение удалено, ключ уничтожается.
rpoplpush <ключ1><ключ2>
: Извлечение одного значения справа из списка <ключ1> и вставка его слева в список <ключ2>.
lrange <ключ><начало><конец>
: Получение элементов по индексу (слева направо)
lrange mylist 0 -1 0
: Левый первый элемент, -1 правый первый элемент, (0 -1 указывает на получение всех элементов)
lindex <ключ><индекс>
: Получение элемента по индексу (слева направо)
llen <ключ>
: Получение длины списка
linsert <ключ> перед/после <значение><новое_значение>
: Вставка нового значения перед/после указанного значения
lrem <ключ><n><значение>
: Удаление n значений слева (слева направо)
lset<ключ><индекс><значение>
: Замена значения элемента с индексом <индекс> в списке <ключ> на новое значениеСтруктура данных
Список использует структуру быстрого списка quickList.
Вначале, при небольшом количестве элементов в списке, используется непрерывная область памяти, которая называется ziplist, то есть сжатый список.Элементы хранятся последовательно в одной непрерывной области памяти.
При большом количестве данных используется структура quicklist.
Обычный связный список требует слишком много дополнительного пространства для указателей, что приводит к неэффективному использованию памяти. Например, если в списке хранятся только данные типа int, структура всё равно требует двух дополнительных указателей prev и next.
Redis объединяет связный список и ziplist в структуру quicklist. То есть несколько ziplist соединены двунаправленными указателями. Это обеспечивает быструю производительность вставки и удаления элементов, а также минимизирует избыточное использование памяти.
Множество предоставляет функциональность, аналогичную функциональности Списка, но имеет особенность автоматического исключения повторяющихся значений. Когда требуется хранение списка данных без повторений, Множество является хорошим выбором. Кроме того, Множество предоставляет важный интерфейс для проверки наличия определенного элемента в множестве, что недоступно для Списка.Redis использует set как неупорядоченное множество строк типа String. Внутренне это представляет собой хэш-таблицу с значением null, поэтому сложность операций добавления, удаления и поиска составляет O(1).Алгоритм, время выполнения которого не зависит от размера данных и всегда равно O(1), будет иметь постоянное время поиска при увеличении количества данных.> sadd <key><value1><value2> .....
:добавляет один или несколько элементов member в множество key, существующие элементы member игнорируются.
smembers <key>
:возвращает все значения из множества.
sismember <key><value>
:проверяет, содержится ли значение value в множестве key, если да — возвращает 1, если нет — возвращает 0.
scard <key>
:возвращает количество элементов в множестве.
srem <key><value1><value2> ....
:удаляет указанные элементы из множества.
spop <key>
:удаляет и возвращает случайный элемент из множества.
srandmember <key><n>
:возвращает случайные n элементов из множества, не удаляя их из него.
smove <source><destination><value>
:перемещает указанный элемент из исходного множества в целевое множество.
sinter <key1><key2>
:возвращает элементы, входящие в пересечение двух множеств.
sunion <key1><key2>
:возвращает элементы, входящие в объединение двух множеств.
sdiff <key1><key2>
:возвращает элементы, входящие в разность двух множеств (элементы из key1, которые отсутствуют в key2).Структура данных
Set структура данных представляет собой словарь, который реализован с помощью хеш-таблицы.
Хеш Redis — это коллекция пар ключ-значение.Хеш Redis — это отображение строка полей и значений. Хеш особенно подходит для хранения объектов.
hset <ключ><поле><значение>
: Устанавливает значение <значение> для поля <поле> в коллекции <ключ>.
hget <ключ1><поле>
: Получает значение поля <поле> из коллекции <ключ1>.
hmset <ключ1><поле1><значение1><поле2><значение2>...
: Устанавливает значения для нескольких полей в хеше.
hexists <ключ1><поле>
: Проверяет, существует ли поле <поле> в хеше <ключ1>.
hkeys <ключ>
: Возвращает все поля хеша <ключ>.
hvals <ключ>
: Возвращает все значения полей хеша <ключ>.
hincrby <ключ><поле><инкремент>
: Увеличивает значение поля <поле> в хеше <ключ> на <инкремент>.
hsetnx <ключ><поле><значение>
: Устанавливает значение поля <поле> в хеше <ключ> на <значение>, если поле еще не существует.
Структура данных
Тип Хеш представлен двумя структурами данных: ziplist (сжатый список) и hashtable (хеш-таблица).
Когда длина полей и значений короткая и их количество небольшое, используется ziplist, в противном случае используется hashtable.
Zset Redis очень похож на обычный набор set, представляющий собой множество уникальных строк.Разница заключается в том, что каждый элемент упорядоченного набора ассоциирован с рейтингом (рейтинг), который используется для сортировки элементов по возрастанию рейтинга. Элементы множества уникальны, но рейтинги могут повторяться.Поскольку элементы упорядочены, они могут быстро извлекаться по рейтингу (score) или позиции (position).
Доступ к средним элементам упорядоченного набора также очень быстр, поэтому его можно использовать как умный список без повторяющихся элементов.> zadd <key><score1><value1><score2><value2>…
: добавляет один или несколько элементов member со своими score значениями в отсортированный набор значений key
zrange <key><start><stop> [WITHSCORES]
: возвращает элементы из отсортированного набора значений key, находящиеся между индексами <start><stop>При использовании WITHSCORES, можно вернуть вместе с элементами их соответствующие score значения
zrangebyscore key min max [withscores] [limit offset count]
: возвращает элементы из отсортированного набора значений key, имеющие score значения между min и max (включительно). Элементы отсортированы по возрастанию значений score.
zrevrangebyscore key max min [withscores] [limit offset count]
: аналогично, но элементы отсортированы по убыванию значений score
zincrby <key><increment><value>
: увеличивает значение score элемента на указанное значение increment
zrem <key><value>
: удаляет элемент с указанным значением из данного множества
zcount <key><min><max>
: подсчитывает количество элементов в данном множестве, имеющих значения score в заданном диапазоне
zrank <key><value>
: возвращает ранг элемента в множестве, начиная с 0.Структура данныхОтсортированный набор (zset) — это очень специфическая структура данных, предоставляемая Redis. С одной стороны, она эквивалентна структуре данных Map<String, Double> в Java, позволяющей каждому элементу value присваивать вес score. С другой стороны, она похожа на TreeSet, так как внутренние элементы сортируются по весу score, что позволяет получить ранг каждого элемента и получать список элементов по диапазону значений score.
Zset использует две структуры данных:
Хэш, который обеспечивает связь между элементом value и весом score, гарантируя уникальность элемента value и возможность получения значения score по элементу value.
Скользящее дерево, которое используется для сортировки элементов value по весу score и получения списка элементов по диапазону значений score.
$###################\space to \space do\space ###################$
Redis публикация и подписка (pub/sub) — это модель обмена сообщениями: отправитель (pub) отправляет сообщение, а получатель (sub) получает его. Клиенты Redis могут подписываться на любое количество каналов.
2. Когда сообщение будет опубликовано на этот канал, оно будет отправлено подписанным клиентам.
subscribe channel # Подписаться на канал publish channel hello # Опубликовать сообщение на канал
Redis транзакция — это отдельная операция, выполненная в изолированном режиме: все команды внутри транзакции сериализуются и выполняются последовательно. В процессе выполнения транзакции команды других клиентов не могут её прервать.
Основное назначение транзакций в Redis — обеспечить последовательное выполнение нескольких команд, предотвращая вклинивание других команд.
Multi
Exec
Discard
После ввода команды Multi все последующие команды будут добавлены в очередь команд, но не будут выполнены до тех пор, пока не будет введена команда Exec. Тогда Redis выполнит все команды из очереди.
В процессе добавления команд в очередь можно использовать команду Discard для отмены текущей транзакции.
Команда успешно создана, данные успешно отправлены
Отказаться от команды
В команде есть ошибочная команда, поэтому команда не выполнится
В команде нет ошибок, но при выполнении возникают ошибки
Если в команде появляется ошибка, то вся команда будет отменена.
Пессимистический блок (Pessimistic Lock), то есть каждый раз, когда мы получаем данные, мы предполагаем, что другие потоки могут их изменять, поэтому каждый раз, когда мы получаем данные, мы блокируем их. Это означает, что другие потоки, желающие получить эти данные, будут заблокированы до тех пор, пока они не получат блокировку. (Это менее эффективно.)
Оптимистический блок (Optimistic Lock), то есть каждый раз, когда мы получаем данные, мы предполагаем, что другие потоки не будут их изменять, поэтому мы не блокируем их. Однако при обновлении данных мы проверяем, не изменили ли другие потоки эти данные за это время. Для этого можно использовать версионирование и другие механизмы.
Оптимистический блок подходит для приложений с большим количеством чтений, так как он увеличивает пропускную способность.
Если в команде появляется ошибка, то вся команда будет отменена.
Пессимистический блок (Pessimistic Lock), то есть каждый раз, когда мы получаем данные, мы предполагаем, что другие потоки могут их изменять, поэтому каждый раз, когда мы получаем данные, мы блокируем их. Это означает, что другие потоки, желающие получить эти данные, будут заблокированы до тех пор, пока они не получат блокировку. (Это менее эффективно.)
Оптимистический блок (Optimistic Lock), то есть каждый раз, когда мы получаем данные, мы предполагаем, что другие потоки не будут их изменять, поэтому мы не блокируем их. Однако при обновлении данных мы проверяем, не изменили ли другие потоки эти данные за это время. Для этого можно использовать версионирование и другие механизмы.
**Оптимистический блок подходит для приложений с большим количеством чтений, так как он увеличивает пропускную способность.**Redis использует эту check-and-set систему для реализации транзакций.
Перед выполнением команды multi выполняется команда watch key1 [key2], которая позволяет наблюдать за одним (или несколькими) ключами. Если ключ был изменён другими командами до выполнения транзакции, то транзакция будет прервана.
Отменяет наблюдение за всеми ключами с помощью команды unwatch. Если после выполнения команды watch были выполнены команды exec или discard, то выполнение команды unwatch не требуется.
Одиночное изолированное выполнение
Все команды внутри транзакции будут последовательно выполнены. В процессе выполнения транзакции она не будет прервана командами других клиентов.
Отсутствие уровней изоляции
Команды в очереди не будут выполнены до тех пор, пока транзакция не будет завершена. До завершения транзакции ни одна команда не будет выполнена.
Не гарантируется атомарность
Если одна команда в транзакции выполнена с ошибкой, следующие команды всё равно будут выполнены, без отката.
В указанные временные интервалы создаются моментальные снимки данных из памяти и записываются на диск, то есть snapshot. При восстановлении данные из файла-снимка загружаются непосредственно в память.
Redis создаёт отдельный дочерний процесс (fork) для выполнения операции сохранения.
Сначала данные записываются во временную файловую систему, после завершения процесса сохранения, содержимое временного файла перезаписывается в dump.rdb.
Весь процесс выполняется без каких-либо операций ввода-вывода со стороны основного процесса, что обеспечивает высокую производительность. Если требуется восстановление большого объёма данных, и полнота восстановления не является критичной, то метод RDB будет более эффективен, чем метод AOF.
Основным недостатком RDB является потеря данных с момента последнего сохранения.
Создаётся копия текущего процесса. Новый процесс имеет все те же данные (переменные, переменные окружения, счетчики выполнения программы и т.д.), но это новый процесс, являющийся потомком исходного процесса.
В Linux программах, вызов fork() создаёт дочерний процесс, полностью идентичный родителю, но обычно дочерний процесс использует системные вызовы типа exec, чтобы заменить свою программу. Для повышения производительности в Linux используется технология копирования при записи.- Обычно родительский и дочерний процессы используют одну и ту же физическую память, только когда содержимое различных областей памяти должно быть изменено, происходит копирование содержимого родительского процесса в дочерний процесс.### Конфигурация> dump имя файла
Конфигурация имени файла в redis.conf по умолчанию равна dump.rdb.
dump путь сохранения
Путь сохранения файла rdb можно изменить. По умолчанию он находится в директории запуска Redis.
stop-writes-on-bgsave-error
При невозможности записи данных на диск операция записи в Redis будет остановлена.
rdbcompression
Указывает, следует ли сжимать файлы при сохранении.
rdbchecksum
Проверка целостности данных, то есть проверка их полноты и точности.
save
Определяет количество операций записи.
Формат: save секунды количество_записей
Записывает каждый выполняемый оператор записи в виде лога (инкрементное сохранение), сохраняя все выполненные операторы записи в Redis (операторы чтения не записываются). Лог можно дополнять, но не изменять, при запуске Redis этот лог используется для восстановления данных. Другими словами, при перезапуске Redis все операторы записи, записанные в лог, выполняются в том же порядке, чтобы восстановить данные.
[always, everysec, no]
в файл AOF на диске;![]()
Имя файла
![]()
AOF частота синхронизации
![]()
appendfsync always
всегда синхронизировать; при каждом внесении данных в Redis они немедленно записываются в журнал;
производительность снижается, но обеспечивается целостность данных.
appendfsync everysec
синхронизация каждую секунду; журнал обновляется один раз в секунду, что может привести к потере данных за последнюю секунду при отказе системы.
appendfsync no
Redis не выполняет активной синхронизации, передавая это управление операционной системой.
Rewrite сжатие
Когда размер файла AOF превышает заданный порог, Redis запускает процесс сжатия содержимого файла AOF, сохраняя минимальное количество команд, необходимых для восстановления данных. Это можно сделать с помощью команды bgrewriteaof.
![]()
Официально рекомендуется использовать оба метода.
Если данные не являются критичными, можно выбрать только RDB.
Не рекомендуется использовать только AOF, так как это может привести к ошибкам.
Если используется только в качестве кэша в памяти, то оба метода могут быть отключены.
Механизм автоматической синхронизации данных между основным сервером и репликами (мастер/слейв), где мастер работает в режиме записи, а слейв — в режиме чтения.
/opt/etc
redis.conf
в текущую директориюcp /etc/redis.conf /opt/etc/
redis.conf
redis6379.conf
redis6380.conf
redis6381.conf
# redis6379.conf
include /opt/etc/redis.conf
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb
# redis6380.conf
include /opt/etc/redis.conf
pidfile /var/run/redis_6380.pid
port 6380
dbfilename dump6380.rdb
# redis6381.conf
include /opt/etc/redis.conf
pidfile /var/run/redis_6381.pid
port 6381
dbfilename dump6381.rdb
info replication
slaveof <ip> <port>
# Преобразование в реплику указанного экземпляра
Проверьте состояние хоста снова.
Успешная сборка.
- Предположим, что слуга 6380 вышел из строя.
Когда 6380 перезапустится, он больше не будет являться слугой 6379, а станет новым мастером; При повторном добавлении 6380 в качестве слуги 6379, слуга полностью скопирует данные с начала до конца.
- Предположим, что мастер 6379 вышел из строя.
6380 и 6381 остаются слугами 6379 и ничего не делают; Когда 6379 перезапустится, он снова станет мастером. ```## Передача огня
Предыдущий slave может стать следующим master для другого slave, а сам slave также может принимать соединения и запросы синхронизации от других slave, таким образом, этот slave становится следующим master в цепочке, что эффективно снижает нагрузку записи на master, децентрализует риск.
slaveof <ip><port>
При изменении маршрута во время работы: будут удалены предыдущие данные, и будет заново создано копирование новых данных.
Когда какой-то slave выходит из строя, все последующие slave не могут выполнять резервное копирование.
То есть, когда мастер выходит из строя, слуги остаются слугами, но не могут продолжать запись данных.
Когда мастер выходит из строя, последующий slave может немедленно стать мастером, а его последующие slave не требуют никаких изменений.
slaveof no one
Автоматическая версия переворота, то есть способность наблюдать за мастером в фоновом режиме и автоматически переключаться на новый мастер при отказе текущего, основываясь на голосовании.
/opt/etc/sentinel.conf
sentinel monitor mymaster 172.16.88.168 6379 1
# mymaster: имя сервера, которое вы назначили для объекта мониторинга
# 1: минимальное количество sentinel, которое должно согласиться с переключением.
```3. Запустите sentinel
```bash
redis-sentinel /opt/etc/sentinel.conf
Когда мастер выходит из строя, из слуг выбирается новый мастер. Правила выбора.
По приоритету, slave-priority/replica-priority, выбирается слуг с наибольшим приоритетом.
По смещению выбираются с большим приоритетом те, у которых смещение больше.
По runid выбираются с большим приоритетом те, у которых значение минимально.
Поскольку все операции записи выполняются сначала на master, а затем синхронизируются и обновляются на slave, то есть некоторый запаздывание при синхронизации с master до slave, которое становится более серьезным при высокой нагрузке. Увеличение количества машин slave также усиливает эту проблему.
После успешного запуска и подключения slave к master последний отправляет команду sync (синхронизация).
Master, получив команду, запускает фоновый процесс сохранения данных, выполняет действия по сохранению данных, собирает все команды, используемые для изменения набора данных, и после завершения работы фонового процесса, master передает весь файл данных (rdb) на slave, чтобы завершить полную синхронизацию.- После выполнения операции записи на основном сервере, данные синхронизируются с сервером-последователем.
Полная синхронизация: когда последователь получает данные файла базы данных, он сохраняет его и загружает в память.
Увеличенная синхронизация: основной сервер продолжает передавать все новые команды изменения данных последовательно на последователь, чтобы завершить синхронизацию.
Любое новое соединение с основным сервером автоматически приведет к выполнению полной синхронизации (полной синхронизации).
Если емкость недостаточна, как redis расширяется?
Как redis распределяет параллельные операции записи?
В режиме мастер-слейва, если основной сервер выходит из строя, что приводит к изменению адреса ip, необходимо изменить конфигурацию приложения, чтобы указать новый адрес основного сервера, порт и т.д.
Решение:
Прокси-сервер ( ранее )
Распределенная конфигурация кластера без центра ( redis3.0 )
Redis кластер обеспечивает горизонтальное расширение redis, то есть запускается n узлов redis, и вся база данных распределяется между этими n узлами, каждый из которых хранит 1/n часть всего набора данных.Redis кластер обеспечивает определённый уровень доступности (доступность) за счёт разделения (*разделения), даже если часть узлов кластера вышла из строя или не может связаться друг с другом, кластер всё равно может обрабатывать запросы.## Настройка Redis-кластера
# В качестве примера используется redis6379.conf
include /opt/etc/redis.conf
pidfile /var/run/redis_6379.pid # Измените
port 6379 # Измените
dbfilename dump6379.rdb # Измените
cluster-enabled yes # Включите режим кластера
cluster-config-file nodes-6379.conf # Установите имя файла конфигурации узла, которое следует изменить
cluster-node-timeout 15000 # Установите время отключения узла, если это превышает указанное время (мс), кластер автоматически выполняет переключение между основным и резервным узлами
# Перед объединением убедитесь, что все экземпляры Redis запущены и файлы конфигурации nodes-xxxx.conf сгенерированы правильно.
# Перейти в директорию установки Redis
/opt/redis-6.2.6/src
# Выполнить
redis-cli --cluster create --cluster-replicas 1 172.16.88.168:6379 172.16.88.168:6380 172.16.88.168:6381 172.16.88.168:6389 172.16.88.168:6390 172.16.88.168:6391
```
4. Подключение с использованием стратегии кластера
```bash
redis-cli -c -p PORT
cluster nodes # Команда для просмотра информации о кластере
Каждый кластер должен иметь как минимум три основных узла.
Параметр
--cluster-replicas 1
указывает, что требуется создать один резервный узел для каждого основного узла в кластере.При распределении узлов следует стремиться к тому, чтобы каждый основной узел работал на разных IP-адресах, а каждый резервный узел не находился на том же IP-адресе, что и его основной узел.
> Redis кластер состоит из 16384 слотов (хэш слот), каждый ключ в базе данных принадлежит одному из этих 16384 слотов.
Кластер использует формулу CRC16(ключ) % 16384 для вычисления того, к какому слоту относится ключ, где CRC16(ключ) используется для вычисления CRC16 контрольной суммы ключа.
Каждый узел в кластере отвечает за обработку части слотов. Например, если кластер может иметь главные узлы, то:
- Узел A отвечает за обработку слотов с номерами от 0 до 5460.
- Узел B отвечает за обработку слотов с номерами от 5461 до 10922.
- Узел C отвечает за обработку слотов с номерами от 10923 до 16383.### Как записывать значения в кластер?
При каждом вводе или запросе ключа с помощью redis-cli Redis вычисляет, к какому слоту должен быть отправлен ключ. Если слот не принадлежит серверу клиента, Redis вернет ошибку и сообщит адрес и порт нужного экземпляра Redis.
redis-cli клиент предоставляет параметр --c для автоматического перенаправления.
Например, после входа с помощью команды redis-cli -c --p 6379, можно автоматически перенаправлять ввод и запросы ключей.
Каждый узел может просматривать только свои слоты.
cluster keyslot <ключ>
: просмотр слота для определенного ключа.
cluster countkeysinslot <слот>
: проверка наличия значений в определенном слоте.
CLUSTER GETKEYSINSLOT <слот> <количество>
: возврат ключей из указанного количества слотов.
![]()
- Когда узел 6379 выходит из строя, узел 6389 становится новым главным узлом.
После восстановления главного узла, как будут изменены отношения между главным и резервным узлами? Главный узел становится резервным.
- Когда узел 6379 перезапускается, он становится резервным узлом для узла 6389.
Если все узлы, отвечающие за определенный диапазон слотов, выходят из строя, сможет ли служба Redis продолжать работу?
- Если все узлы, отвечающие за определенный диапазон слотов, выходят из строя, и параметр cluster-require-full-coverage установлен в yes, весь кластер выйдет из строя.
- Если все узлы, отвечающие за определенный диапазон слотов, выходят из строя, и параметр cluster-require-full-coverage установлен в no, данные для этого диапазона слотов станут недоступными для использования и хранения.
Параметр
cluster-require-full-coverage
в конфигурационном файлеredis.conf
Преимущества- Реализация масштабируемости;
То есть Java операции с Redis.
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
> ***Ключевые слова***
>
> ```java
> jedis.set("k1", "v1");
> jedis.set("k2", "v2");
> jedis.set("k3", "v3");
> Set<String> keys = jedis.keys("*");
> System.out.println(keys.size());
> for (String key : keys) {
> System.out.println(key);
> }
> System.out.println(jedis.exists("k1"));
> System.out.println(jedis.ttl("k1"));
> System.out.println(jedis.get("k1"));
> ```
>
> ***Строки***
>
> ```java
> jedis.mset("str1","v1","str2","v2","str3","v3");
> System.out.println(jedis.mget("str1","str2","str3"));
> ```
>
> ***Списки***
>
> ```java
> List<String> list = jedis.lrange("mylist",0,-1);
> for (String element : list) {
> System.out.println(element);
> }
> ```
>
> ***Множества***
>
> ```java
> jedis.sadd("orders", "order01");
> jedis.sadd("orders", "order02");
> jedis.sadd("orders", "order03");
> jedis.sadd("orders", "order04");
> Set<String> smembers = jedis.smembers("orders");
> for (String order : smembers) {
> System.out.println(order);
> }
> jedis.srem("orders", "order02");
> ```
>
> ***Хэши***
>
> ```java
> jedis.hset("hash1","userName","lisi");
> System.out.println(jedis.hget("hash1","userName"));
> Map<String,String> map = new HashMap<String,String>();
> map.put("telphone","13810169999");
> map.put("address","atguigu");
> map.put("email","abc@163.com");
> jedis.hmset("hash2",map);
> List<String> result = jedis.hmget("hash2", "telphone","email");
> for (String element : result) {
> System.out.println(element);
> }
> ```
>
> ***zset***
>
> ```java
> jedis.zadd("zset01", 100d, "z3");
> jedis.zadd("zset01", 90d, "l4");
> jedis.zadd("zset01", 80d, "w5");
> jedis.zadd("zset01", 70d, "z6");
>
> Set<String> zrange = jedis.zrange("zset01", 0, -1);
> for (String e : zrange) {
> System.out.println(e);
> }
> ```
## Основные операции с использованием Jedis```java
private static JedisSentinelPool jedisSentinelPool = null;
public static Jedis getJedisFromSentinel() {
if (jedisSentinelPool == null) {
Set<String> sentinelSet = new HashSet<>();
sentinelSet.add("172.16.88.168:26379"); // порт для sentinel
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10); // максимальное количество доступных соединений
jedisPoolConfig.setMaxIdle(5); // максимальное количество свободных соединений
jedisPoolConfig.setMinIdle(5); // минимальное количество свободных соединений
jedisPoolConfig.setBlockWhenExhausted(true); // ждать при исчерпании соединений
jedisPoolConfig.setMaxWaitMillis(2000); // время ожидания
jedisPoolConfig.setTestOnBorrow(true); // проверять соединение при заимствовании
jedisSentinelPool = new JedisSentinelPool("mymaster", sentinelSet, jedisPoolConfig); // имя сервисного хоста
return jedisSentinelPool.getResource();
} else {
return jedisSentinelPool.getResource();
}
}
Даже если подключение не осуществляется к основному серверу, кластер автоматически переключается на основной сервер для хранения данных. Запись производится на основном сервере, а чтение — на репликах.
Без центральной системы репликации. Независимо от того, какой сервер используется для записи данных, данные могут быть прочитаны с других серверов.
public class JedisClusterTest {
public static void main(String[] args) {
Set<HostAndPort> set = new HashSet<HostAndPort>();
set.add(new HostAndPort("172.16.88.168", 6379)); // любой из портов
JedisCluster jedisCluster = new JedisCluster(set);
jedisCluster.set("k1", "v1");
System.out.println(jedisCluster.get("k1"));
}
}
```# Интеграция Redis в SpringBoot
1. Зависимости
```xml
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring2.x интеграция redis требует common-pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.0</version>
</dependency>
# Адрес сервера Redis
spring.redis.host=ip
# Порт подключения к серверу Redis
spring.redis.port=6379
# Индекс базы данных Redis (по умолчанию 0)
spring.redis.database=0
# Время ожидания соединения (миллисекунды)
spring.redis.timeout=1800000
# Максимальное количество активных соединений в пуле (отрицательное значение указывает на отсутствие ограничений)
spring.redis.lettuce.pool.max-active=20
# Максимальное время ожидания блокировки (отрицательное значение указывает на отсутствие ограничений)
spring.redis.lettuce.pool.max-wait=-1
# Максимальное количество свободных соединений в пуле
spring.redis.lettuce.pool.max-idle=5
# Минимальное количество свободных соединений в пуле
spring.redis.lettuce.pool.min-idle=0
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// решение проблемы преобразования при запросе к кешу
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// конфигурация сериализации (решение проблемы с кодировкой), время жизни 600 секунд
RedisCacheConfiguration config =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
```# Решение проблем с кэшированием
## Проблема пробития кэша
<img src="https://gitee.com/tsuiraku/typora/raw/master/img/%E6%88%AA%E5%B1%8F2021-10-31%2015.02.58.png" style="zoom:50%;" />
### Признаки
Данные, соответствующие ключу **key**, отсутствуют в источнике данных. Каждый запрос к этому ключу не может получить данные из кэша и поэтому переходит к источнику данных, что может привести к перегрузке последнего.
Например, если использовать несуществующий идентификатор пользователя для получения информации о пользователе, то ни в кэше, ни в базе данных данных не будет. В случае, если хакер использует эту уязвимость для атаки, это может привести к перегрузке базы данных.Результат:
1. Увеличение нагрузки на сервер приложений.
2. Уменьшение скорости попадания в кэш Redis $\longrightarrow$ запрос к базе данных.
### Как решить
- **Кэширование пустых значений**
Если запрос возвращает пустое значение (независимо от того, существует ли данное значение), все равно кэшировать это пустое значение (null). Устанавливать короткий срок годности для пустого значения, не более пяти минут.
- **Создание списка доступных идентификаторов (белого списка)**
Использовать тип данных bitmaps для определения списка доступных идентификаторов. Идентификаторы в списке используются как смещения в bitmaps. При каждом обращении сравниваются идентификаторы запроса и идентификаторы в bitmaps. Если идентификатор запроса отсутствует в bitmaps, обращение блокируется.
- **Использование фильтра Блума**
Фильтр Блума (Bloom Filter) был предложен Блумом в 1970 году. Это длинная двоичная последовательность (карта битов) и набор случайных отображений (хеш-функций).
Фильтр Блума используется для проверки наличия элемента в множестве. Его преимуществами являются высокая эффективность использования пространства и скорость запросов, недостатками — возможная ошибка при распознавании и трудности при удалении.Все возможные данные хешируются в достаточно большую карту битов. Определённый несуществующий элемент будет заблокирован этой картой битов, что предотвращает запросы к основному хранилищу данных.- **Мониторинг в реальном времени**
Когда заметно, что скорость попадания в кэш Redis начинает быстро снижаться, следует проверить объекты и данные, к которым обращаются, и сотрудничать с операционной службой для установки черного списка ограничений.
## Проблема пробоя кэша
<img src="https://gitee.com/tsuiraku/typora/raw/master/img/%E6%88%AA%E5%B1%8F2021-10-31%2015.18.09.png" style="zoom:50%;" />
Данные, соответствующие ключу key, существуют, но истекли в кэше Redis. В этот момент, если придет большое количество параллельных запросов, эти запросы обнаружат, что кэш истек, и будут загружать данные из базы данных и снова помещать их в кэш. В этот момент большое количество параллельных запросов может мгновенно перегрузить базу данных.1. Внезапное увеличение нагрузки на доступ к базе данных.
2. В Redis не произошло массового истечения срока действия ключей, Redis работает нормально.
3. (то есть какой-то часто используемый ключ истёк, и вдруг возникло множество запросов к этому ключу)
### Как решить
- Предварительное хранение популярных данных
Перед пиковой нагрузкой на Redis можно заранее загрузить некоторые популярные данные, увеличив время жизни этих ключей.
- Динамическое регулирование
В реальном времени отслеживать популярные данные и динамически корректировать время жизни ключей.- Использование блокировки или очереди
## Кэш- Avalanche
Когда данные, соответствующие ключу, существуют, но истекают в ***Redis***, и в этот момент приходит большое количество параллельных запросов, эти запросы обнаруживают истечение срока действия кэша и загружают данные из базы данных (***DB***) и снова помещают их в кэш. В этом случае большое количество параллельных запросов может мгновенно перегрузить базу данных (***DB***).
Разница между кэш-avalanche и кэш-hit заключается в том, что в первом случае происходит истечение срока действия кэша для нескольких ключей, а во втором — для одного ключа.
1. Увеличение нагрузки на базу данных.
2. В очень короткий промежуток времени происходит концентрация запросов на большое количество истёкших ключей.
### Как решить
- **Создание многоуровневой системы кэширования**
***Nginx*** кэш + ***Redis*** кэш + другие кэши (***Ehcache*** и т.д.)
- **Использование блокировки или очереди:**
Используйте блокировку или очередь, чтобы гарантировать, что большое количество потоков одновременно не будут выполнять чтение/запись в базе данных, тем самым предотвращая перегрузку системы хранения при истечении срока действия кэша. Не применимо для высоконагруженных систем.
- **Установка метки истечения срока действия и обновление кэша:**
Отслеживайте истечение срока действия кэша (с учетом запаса времени), если кэш истёк, это будет триггером для запуска другого потока для обновления кэша ключа в фоновом режиме.- **Распределение времени истечения срока действия кэша:**
Например, можно добавить случайное значение к существующему сроку действия, например, от 1 до 5 минут, таким образом, повторяемость времени истечения срока действия каждого кэша будет снижена, что затруднит возникновение массового истечения срока действия кэша.
## Распределенная блокировка
$\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\space to \space do\space \#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#$
# Основные понятия
## 1. 9 типов данных в Redis
Redis имеет девять основных типов данных: String, List, Hash, Set, Sorted Set, Bitmap, Hyperlog, Geo и Stream. String: самый базовый тип данных, двоичная безопасность строки, максимальный размер 512М.
List: список строк, который сохраняет порядок добавления элементов.
Set: множество строк без учета порядка, в котором отсутствуют повторяющиеся элементы.
SortedSet: отсортированное множество строк.
Hash: коллекция пар ключ-значение.
Bitmap: более детализированное представление, основанное на битах.
Hyperlog: вероятностная структура данных. # 2.8.9 добавлено
Geo: хранение географической информации и выполнение операций с этими данными. # 3.2 добавлено
Stream (поток). # 5.0 добавлено
## 2. Применение Redis
Взаимодействие с реляционными базами данных для создания кэша.
Обработка высокочастотных данных с большим количеством запросов, снижение нагрузки на ввод-вывод базы данных.Используя его способность к сохранению состояния, можно использовать различные структуры данных для хранения специфических данных.
Последние N данных → с использованием List для естественной сортировки данных.
Рейтинг, TopN → с использованием zset (упорядоченного множества).
Временные данные, такие как коды подтверждения для мобильных телефонов → Expire (время жизни).
Счетчики, распродажи → атомарность, методы INCR и DECR для увеличения и уменьшения значений.
Удаление повторяющихся данных из большого объема данных → с использованием множества set.
Создание очередей → с использованием множества list.
Система публикации и подписки → модель pub/sub.
## 3. По умолчанию директория установки /usr/local/bin
Redis-benchmark: инструмент для тестирования производительности, который можно запустить на своем компьютере, чтобы проверить производительность своего компьютера (выполняется после запуска службы).
Redis-check-aof: исправление поврежденных AOF файлов, rdb и aof будут рассмотрены позже.
Redis-check-dump: исправление поврежденных dump.rdb файлов.
Redis-sentinel: использование Redis в режиме кластера.
Redis-server: запуск Redis в режиме командной строки.
## 4. Различия между Redis и Memcached- **Структура данных**: Redis поддерживает 5 типов структур данных; Memcached поддерживает только строки
- **Производительность**: при работе с небольшими объемами данных Redis работает быстрее Memcached; при работе с большими объемами данных Redis немного уступает
- **Постоянство данных**: Redis поддерживает постоянство данных; Memcached все данные хранятся в оперативной памяти
- **Модель работы с потоками**: **Redis использует однопоточную модель + механизм IO многоканального ввода-вывода**, без переключения потоков; Memcached использует многопоточную модель + механизм блокировки, один основной поток, несколько рабочих потоков
- **Восстановление после аварий**: после потери данных Redis можно восстановиться с помощью aof; после отказа Memcached данные не могут быть восстановлены
- **Режим кластера**: Redis поддерживает native режим cluster; Memcached не имеет native режима кластера## 5. Многоканальное ввод-вывод
Почему Redis использует технологию многоканального ввода-вывода? Потому что Redis работает в **однопоточной модели**, все операции выполняются последовательно. Однако **ожидание ввода или вывода данных является блокирующей операцией**, поэтому операции ввода-вывода обычно не могут вернуться сразу. Это приводит к тому, что блокировка одного файла ввода-вывода может привести к невозможности обслуживания других клиентов. Многоканальное ввод-вывод было разработано для решения этой проблемы. **Чтобы однопоточный (процесс) сервер мог одновременно обслуживать несколько клиентов, Redis использует механизм многоканального ввода-вывода.** Здесь **"множественный"** означает несколько сетевых соединений клиентов, а **"взаимозамена"** относится к использованию одного и того же потока (однопроцессного). Ввод-вывод множественной взаимозамены фактически использует один поток для проверки состояния готовности нескольких сокетов, управляя несколькими потоками ввода-вывода через отслеживание состояния каждого сокета (потока ввода-вывода) в одном потоке. Ниже приведена схема модели ввода-вывода множественной взаимозамены Redis:

Приведите описание I/O-множественного соединения Redis:- (1) При установлении соединения между одним клиентом и сервером с помощью сокета создается соответствующий дескриптор сокета (дескриптор сокета является типом дескриптора файла). Каждое сетевое соединение сокета фактически соответствует одному дескриптору файла.
- (2) При установлении соединения несколькими клиентами с сервером Redis использует **"многопоточную программу I/O"** для регистрации дескриптора файла (FD) каждого сокета клиента в списке прослушивания (очереди). Когда клиент выполняет команды чтения или записи, многопоточная программа I/O упаковывает команду в событие и связывает её с соответствующим FD.
- (3) **"Обработчик событий файлов"** использует модуль I/O многопоточной программы для одновременного мониторинга нескольких дескрипторов файлов (FD) для чтения и записи. Когда происходит событие файла, такое как `accept`, `read`, `write` или `close`, обработчик событий файлов вызывает соответствующий обработчик событий, связанный с FD, для выполнения команд.- (5) Обработчик событий файлов работает в одном потоке, но благодаря использованию модуля I/O множественного соединения, он может одновременно мониторить несколько FD для чтения и записи. Когда один из клиентов достигает состояния записи или чтения, обработчик событий файлов немедленно выполняется, что позволяет избежать блокировки I/O и повышает производительность сетевой связи.
- (6) Как показано на рисунке выше, Redis использует модель I/O множественного соединения, реализованную с помощью **"реакторных настроек"**.### **"Заключение"**
- (1) Функции I/O множественного соединения Redis включают select, poll, epoll, kqueue. Select используется как альтернативный вариант, поскольку он требует сканирования всех прослушиваемых дескрипторов файлов при использовании и может обслуживать только 1024 файла одновременно, поэтому он является альтернативным вариантом.
- (2) Модель I/O множественного соединения использует возможность функций select, poll, epoll одновременно отслеживать несколько потоков I/O. В свободное время текущий поток блокируется. Когда одно или несколько потоков имеют события I/O, они пробуждаются из блокированного состояния, и программа проверяет все потоки (для epoll проверяются только те потоки, которые действительно имеют события), последовательно выполняя обработку готовых потоков, что позволяет избежать большого количества бесполезного ожидания.## 6. Часто используемые команды для типа данных String в Redis
| Параметр | Описание |
| --------- | :--------------------------------------------------------------------------------------- |
| Get | Get key-name —— Получает значение, хранящееся в указанном ключе |
| Mget | Mget key-name [key-name…] —— Получает значения, хранящиеся в указанных ключах |
| Strlen | Strlen key-name —— Получает длину значения, хранящегося в указанном ключе, где длина китайского символа равна 2 |
| Set | Set key-name value —— Устанавливает значение, хранящееся в указанном ключе |
| Mset | Mset key-name value [key value…] —— Устанавливает значения, хранящиеся в указанных ключах |
| Getset | Getset key-name newvalue —— Устанавливает новое значение для указанного ключа и возвращает старое значение этого ключа |
| Del | Del key-name/Del key-name1 key-name2 —— Удаляет значения, хранящиеся в указанных ключах (этот команд используется для всех типов) |
| Incr | Incr key-name —— Увеличивает значение, хранящееся в указанном ключе на 1. Если ключ существует, то текущее значение должно быть целым числом; если ключ не существует, то после увеличения get(key) = 1 |
| Decr | Decr key-name —— Уменьшает значение, хранящееся в указанном ключе на 1. Если ключ существует, то текущее значение должно быть целым числом; если ключ не существует, то после уменьшения get(key) = -1 |
| IncrBy | IncrBy key-name amount —— Увеличивает значение, хранящееся в указанном ключе на целое число amount |Если ключ существует, то текущее значение должно быть целым числом; если ключ не существует, то после увеличения get(key) = amount |
| DecrBy | DecrBy key-name amount —— Уменьшает значение, хранящееся в указанном ключе на целое число amount. Если ключ существует, то текущее значение должно быть целым числом; если ключ не существует, то после уменьшения get(key) = -amount |
| IncrByFloat | IncrByFloat key-name amount —— Увеличивает значение, хранящееся в указанном ключе на вещественное число amount. Если ключ существует, то текущее значение должно быть числом; если ключ не существует, то после увеличения get(key) = amount |
| Append | Append key-name value —— Добавляет значение value к концу текущего значения, хранящегося в указанном ключе |
| Getrange | Getrange key-name start end —— Получает подстроку, состоящую из символов с позиции start до позиции end, включая start и end |
| Setrange |Setrange key-name offset value —— Устанавливает подстроку, начиная с позиции offset, на указанное значение, включая offset |
## 7. Поддержка хранения списков в Redis***Redis*** списки представляют собой простые списки строк, отсортированные по порядку вставки. Вы можете добавлять элементы в начало (слева) или конец (справа) списка.
**Под底层 это двусвязный список**, что обеспечивает высокую производительность операций с обоих концов списка. Однако производительность операций с элементами по индексу может быть ниже.
<img src="https://gitee.com/tsuiraku/typora/raw/master/img/image-20211022121129201.png" style="zoom:50%;" />
***Список*** использует структуру данных ***quickList***.
**При небольшом количестве элементов используется непрерывная область памяти**, которая представляет собой структуру ***ziplist***, то есть сжатый список.
Элементы хранятся последовательно в одной непрерывной области памяти.
Когда количество данных становится большим, используется структура ***quicklist***.
Обычный связный список требует слишком много дополнительного пространства для указателей, что приводит к большому расходу памяти. Например, если в списке хранятся только данные типа ***int***, структурно требуется два дополнительных указателя ***prev*** и ***next***.
***Redis*** объединяет связный список и ***ziplist*** в структуру ***quicklist***. То есть несколько ***ziplist*** соединены между собой двусвязными указателями. Это позволяет обеспечивать быструю производительность вставки и удаления элементов, при этом не создавая значительных излишков памяти.
***Redis*** объединяет связный список и ***ziplist*** в структуру ***quicklist***. То есть несколько ***ziplist*** соединены между собой двусвязными указателями. Это позволяет обеспечивать быструю производительность вставки и удаления элементов, при этом не создавая значительных излишков памяти.
**Под底层 это двусвязный список** — это двусвязный список, что обеспечивает высокую производительность операций с обоих концов списка. Однако производительность операций с элементами по индексу может быть ниже.<img src="https://gitee.com/tsuiraku/typora/raw/master/img/image-20211022122514593.png" style="zoom:50%;" />
**Основные команды**
> `lpush/rpush <ключ> <значение1> <значение2> <значение3> ...`: Вставка одного или нескольких значений слева/справа.
>
> ```
> lpush k1 v1 v2 v3
> lrange k1 0 -1
> вывод: v3 v2 v1
>
> rpush k1 v1 v2 v3
> rrange k1 0 -1
> вывод: v1 v2 v3
> ```
>
> `lpop/rpop <ключ>`: Удаление одного значения слева/справа. **Если значение существует, ключ существует; если значение удалено, ключ уничтожается.**
>
> `rpoplpush <ключ1> <ключ2>`: Удаление одного значения справа из списка ***<ключ1>*** и вставка его слева в список ***<ключ2>***.
>
> `lrange <ключ> <начало> <конец>`: Получение элементов по индексу (слева направо)
>
> `lrange mylist 0 -1 0`: Левый первый элемент, правый первый элемент, (0 -1 означает получение всех элементов)
>
> `lindex <ключ> <индекс>`: Получение элемента по индексу (слева направо)
>
> `llen <ключ>`: Получение длины списка
>
> `linsert <ключ> before/after <значение> <новое_значение>`: Вставка нового значения перед/после указанного значения
>
> `lrem <ключ> <n> <значение>`: Удаление n значений типа value слева (слева направо)
>
> `lset <ключ> <индекс> <значение>`: Замена значения элемента с индексом index в списке ключа на новое значение
## 8. Внутреннее хранение множества Set в Redis
***Redis***'s ***Set*** — это неупорядоченное множество типов ***String***. На самом деле его внутреннее представление представляет собой хэш-таблицу с значением ***null***, поэтому сложность операций добавления, удаления и поиска составляет ***O(1)***.Алгоритм, при котором время выполнения операции остаётся постоянным независимо от увеличения объёма данных, имеет сложность ***O(1)***.
**Основные команды**
sadd <ключ><значение1><значение2> .....
: Добавляет один или несколько элементов member в множество key, существующие элементы будут проигнорированы
smembers <ключ>
: Получает все значения из множества.
sismember <ключ><значение>
: Проверяет, содержит ли множество <ключ> значение <значение>, если да, возвращает 1, если нет, возвращает 0
scard <ключ>
: Возвращает количество элементов в множестве.
srem <ключ><значение1><значение2> ....
: Удаляет указанные элементы из множества
spop <ключ>
: Удаляет случайный элемент из множества
srandmember <ключ><n>
: Выбирает случайным образом n элементов из множества, не удаляя их
smove <источник><назначение>
: Перемещает элемент из одного множества в другое
sinter <ключ1><ключ2>
: Возвращает пересечение двух множеств
sunion <ключ1><ключ2>
: Возвращает объединение двух множеств
sdiff <ключ1><ключ2>
: Возвращает разность двух множеств (элементы, содержащиеся в key1, но не содержащиеся в key2)
## 9. Хеш-таблицы Hash в Redis и основные команды
***Redis hash*** — это карта, которая связывает ***field*** типа ***String*** с соответствующими ***value***, что делает её особенно подходящей для хранения объектов.**Структура данных**
Для хеш-таблиц используется две структуры данных: ***ziplist*** (сжатый список) и ***hashtable*** (хэш-таблица).
Когда длина ***field-value*** короткая и их количество мало, используется ***ziplist***, в противном случае используется ***hashtable***.> `hset <ключ> <поле> <значение>`: присваивает значение ***<значение>*** полю ***<поле>*** в коллекции ***<ключ>***
>
> `hget <ключ1> <поле>`: извлекает значение ***value*** из поля ***<поле>*** в коллекции ***<ключ1>***
>
> `hmset <ключ1> <поле1> <значение1> <поле2> <значение2> ...`: устанавливает значения для полей хэша
>
> `hexists <ключ1> <поле>`: проверяет наличие поля ***<поле>*** в хэш-таблице ***<ключ1>***
>
> `hkeys <ключ>`: возвращает все поля хэш-коллекции ***<ключ>***
>
> `hvals <ключ>`: возвращает все значения хэш-коллекции ***<ключ>***
>
> `hincrby <ключ> <поле> <инкремент>`: увеличивает значение поля ***<поле>*** в хэш-таблице ***<ключ>*** на значение ***<инкремент>***
>
> `hsetnx <ключ> <поле> <значение>`: устанавливает значение поля ***<поле>*** в хэш-таблице ***<ключ>*** на значение ***<значение>***, если поле ***<поле>*** еще не существует
## 10. Транзакции и механизмы блокировки в Redis
***MULTI***
***EXEC***
***DISCARD***
С момента отправки команды ***MULTI*** все последующие команды будут добавлены в очередь команд, но не будут выполнены до тех пор, пока не будет отправлена команда ***EXEC***. После этого Redis выполнит все команды из очереди.В процессе добавления команд в очередь можно использовать команду ***DISCARD*** для отмены текущей транзакции.
## 11. Понимание распределённых блокировок в Redis?
## 12. Политики истечения срока действия кэша Redis
## 13. Алгоритм LRU в Redis
## 14. Преимущества и недостатки Redis
**Преимущества**
Отличные показатели производительности при чтении и записи — Redis способен выполнять до 110 000 операций чтения в секунду и до 81 000 операций записи в секунду.
Поддержка долговременного хранения данных, включая два метода: AOF и RDB.
Поддержка транзакций, все операции Redis атомарны, а также поддерживается выполнение нескольких операций как единой атомарной операции.
Разнообразие структур данных, включая поддержку типов данных string, hash, set, zset и list.
Поддержка репликации между главным и вторичным серверами, автоматическое синхронизирование данных с главного сервера на вторичный, что позволяет осуществлять разделение нагрузки на чтение и запись.
**Недостатки**
Объём хранимых данных ограничен объёмом физической памяти, поэтому Redis не подходит для работы с большими объёмами данных. Он лучше всего подходит для высокопроизводительных операций и вычислений с небольшим количеством данных.Redis не имеет встроенной функции аварийного восстановления, поэтому любое отключение главного или вторичного сервера приведёт к временному прекращению доступа к данным, что требует перезапуска или ручного изменения IP-адреса для восстановления.При отключении главного сервера могут возникнуть проблемы с согласованностью данных, если часть данных не успела синхронизироваться перед отключением. Это снижает надёжность системы.
Redis сложно масштабировать онлайн, увеличение объёма кластера может стать сложной задачей. Для предотвращения этой проблемы, системные администраторы должны заранее обеспечить достаточное количество ресурсов, что приводит к неэффективному использованию ресурсов.
## 15. Какова система долговременного хранения Redis? Что такое её преимущества и недостатки?
Redis предлагает две системы долговременного хранения: RDB (по умолчанию) и AOF.
**RDB: Redis Database Backup**
RDB является основным методом долговременного хранения Redis. В соответствии с определённым интервалом времени данные из памяти сохраняются в виде снимка на диск, создавая файл dump.rdb. Интервалы сохранения определяются параметром `save` в конфигурационном файле.
- 1. Только один файл dump.rdb, что облегчает процесс сохранения данных.
- 2. Хорошая устойчивость к отказам, так как все данные хранятся в одном файле, который можно переместить на надежный носитель.
- 3. Максимальная производительность, **вилка (fork)** подпроцесса используется для выполнения операций записи, позволяя основному процессу продолжать обработку команд. Таким образом, достигается максимальная производительность ввода-вывода. Основной процесс не выполняет никаких операций ввода-вывода, что гарантирует высокую производительность Redis.
- 4. При больших объемах данных запуск RDB быстрее, чем запуск AOF.
Недостатки:- 1. **Низкая безопасность данных. RDB периодически выполняет сохранение данных, но если между сохранениями Redis выйдет из строя**, произойдет потеря данных. Этот метод лучше всего подходит для ситуаций, где требования к данным не являются строгими.
- 2. Метод AOF (Append-only file) сохраняет все команды, записанные в Redis, в виде протокола запросов Redis в отдельный файл AOF.
**AOF: Сохранение**
Сохранение AOF (только-для-записи файл) заключается в том, чтобы записывать каждую команду записи Redis в отдельный лог-файл. При перезапуске Redis данные восстанавливаются из этого лог-файла.
При одновременном использовании обоих методов восстановление Redis будет приоритетно использовать AOF для восстановления данных.

Преимущества:
- 1. Более высокая безопасность данных, так как можно настроить параметр appendfsync, который может быть установлен на always, что означает, что каждое выполнение команды будет записано в файл AOF.
- 2. Используя режим записи append, даже если сервер внезапно выйдет из строя, можно использовать инструмент redis-check-aof для решения проблем с согласованностью данных.
- 3. Механизм переписывания AOF. Перед тем как файл AOF будет переписан (когда он становится слишком большим), можно удалить некоторые команды (например, случайные команды flushall).Недостатки:
- 1. **Файл AOF больше по размеру, чем файл RDB, и восстановление данных из него занимает больше времени**.
- 2. При больших объемах данных, запуск Redis с использованием AOF менее эффективен, чем с использованием RDB.
Преимущества и недостатки:
- Файл AOF обновляется чаще, чем файл RDB, и приоритетно используется для восстановления данных.
- **AOF более безопасен, но и больше по размеру, чем RDB**.
- RDB обеспечивает лучшую производительность по сравнению с AOF.
- Если оба метода настроены, при запуске Redis будет использоваться AOF.
## 16. Как расширять данные Redis и кэширование?
- Если Redis используется как кэш, можно использовать **однородное хеширование** для динамического расширения и уменьшения количества узлов.
- Если Redis используется как хранилище данных, необходимо использовать фиксированное **отображение ключей на узлы**, количество узлов после его установки не должно меняться. В противном случае (т.е., если требуется динамическое изменение количиства узлов Redis), необходимо использовать систему, которая может выполнять балансировку данных во время работы, а это возможно только с использованием кластера Redis.
## 17. Механизм отсеивания Redis
Если использование памяти Redis становится слишком большим, начинается процесс отсеивания данных, имеются следующие стратегии:**Ошибка при записи**: noeviction: когда память не может вместить новые данные, новые операции записи будут завершаться ошибкой; этот метод обычно никто не использует. **Удаление недавно наименее используемого ключа**: allkeys-lru: когда память не может вместить новые данные, удаляются ключи, которые наименее использовались в пространстве ключей (это самый распространенный метод).
**Случайное удаление ключа**: allkeys-random: когда память не может вместить новые данные, случайным образом удаляется один ключ из пространства ключей (этот метод обычно никто не использует).
**Удаление наименее используемого ключа с истекающим сроком действия**: volatile-lru: когда память не может вместить новые данные, удаляются ключи, которые наименее использовались и имеют установленный срок действия в пространстве ключей (этот метод обычно не очень подходит).
**Случайное удаление ключа с истекающим сроком действия**: volatile-random: когда память не может вместить новые данные, случайным образом удаляется один ключ с установленным сроком действия из пространства ключей.
**Удаление ключа с более ранним сроком действия**: volatile-ttl: когда память не может вместить новые данные, удаляются ключи с более ранним сроком действия из пространства ключей с установленным сроком действия.## 18. Три этапа транзакций Redis
1. Начало транзакции MULTI
2. Включение команд в очередь
3. Выполнение транзакции EXEC
При выполнении транзакции, если сервер получает запросы, отличные от EXEC, DISCARD, WATCH, MULTI, они помещаются в очередь.
## 19. Поддерживает ли Redis транзакции свойство изолированности?
Redis — это однопоточное приложение, которое гарантирует выполнение всех команд в транзакции без прерываний. Поэтому транзакции Redis всегда изолированы.
## 20. Обеспечивает ли Redis транзакции атомарность и возможность отката?
В Redis каждая отдельная команда выполняется атомарно, но транзакции не гарантируют атомарность и не поддерживают откат. Если одна команда в транзакции завершается ошибкой, остальные команды всё равно будут выполнены.
## 21. Другие реализации транзакций Redis
На основе Lua-скриптов Redis обеспечивает выполнение команд внутри скрипта последовательно и одновременно, но не предоставляет отката при возникновении ошибок во время выполнения. Если часть команд выполнится с ошибками, остальные команды всё равно будут выполнены.
**На основе промежуточной метки**: через дополнительную метку проверяется завершение транзакции, читаются данные, сначала проверяется метка для определения завершения транзакции. Но это требует написания дополнительного кода, что усложняет процесс.## 22. Разные ситуации ошибок при выполнении транзакций Redis
Если Redis выдает ошибку при добавлении команд в очередь, то транзакция не будет выполнена. Если Redis не выдает ошибку при добавлении команд в очередь, то EXEC выполнит команды, которые не вызвали ошибку.
## 23. Алгоритм, используемый Redis для возврата использования
Алгоритм LRU
## 24. Три режима работы Redis-кластера
### 1) Режим репликации с мастером и слейвами
Синхронизация данных, данные между узлами полные
Redis предоставляет функцию репликации, которая позволяет автоматически синхронизировать обновленные данные с одного сервера на другие.
**Удовлетворяет AP в CAP**
**Принцип работы**
Когда слейв запускается, он отправляет команду sync мастеру, который начинает создание снимка RDB в фоновом режиме. Временно получаемые команды кэшируются. Когда снимок готов, мастер отправляет его вместе с кэшированными командами слейву. Инициализация репликации завершена.
После этого мастер отправляет каждую новую команду сразу же слейву. При возобновлении соединения после разрыва, версии Redis 2.8 и выше передают команды, которые были получены во время разрыва. Увеличенная репликация.Репликация с мастером и слейвами является оптимистичной, когда клиент отправляет команду записи мастеру, мастер выполняет её и немедленно возвращает результат клиенту, а затем асинхронно отправляет команду слейву, что не влияет на производительность. Также можно настроить минимальное количество слейвов, которым должны быть отправлены команды, прежде чем запись считается выполненной.
Бездисковая репликация: если производительность жёсткого диска низкая, это может замедлить процесс репликации. Версии Redis 2.8 и выше поддерживают настройку бездисковой репликации, repl-diskless-sync yes### 2) Режим с Sentinel
### 3) Режим кластера (cluster-enable)
Каждый узел хранит часть данных.
## 25. Различия между Redis и Zookeeper в распределённых системах
Теория CAP гласит, что распределённая система может одновременно удовлетворять максимум двум из трёх свойств: согласованность (Consistency), доступность (Availability) и устойчивость к разделению (Partition tolerance).
Redis удовлетворяет AP — доступность и устойчивость к разделению.
Zookeeper удовлетворяет CP — согласованность и устойчивость к разделению.
## 26. Три режима работы Redis-кластера
Первый — это режим master-slave, простой режим с мастером и слейвами;
Второй — режим sentinel, режим с Sentinel, где есть дополнительный Sentinel, который поможет вам сделать переключение между мастером и слейвом, если мастер выйдет из строя, без необходимости вмешательства человека;
Третий — режим кластера (cluster-enable), режим кластера, где несколько узлов хранят разные данные. На каждом узле есть так называемый слот, диапазон от 0 до 16383. Каждый раз, когда приходит новая запись, она преобразуется в число с помощью CRC16, затем берётся остаток от деления на 16384, и таким образом узнаётся, на каком узле находится этот слот. В конечном итоге запись попадает на соответствующий узел. Для обеспечения высокой доступности каждый узел также имеет режим master-slave.## 27. Принцип работы и недостатки реализации распределённого блокчейна Redisson
Redisson на основе Redis реализовал интерфейс `Lock` для распределённой кластерной блокировки. Это рекурсивная блокировка с мощными возможностями и сложным исходным кодом, более надёжная, чем одиночный режим Redis, с высокой стабильностью. Поддерживает кластерный режим и автоматическое отложенное освобождение блокировки в зависимости от бизнес-времени.При сбое основного экземпляра Redis могут возникнуть ситуации, когда несколько клиентов одновременно получают блокировку. Если требуется сильная консистентность, то следует рассмотреть использование распределённой блокировки Zookeeper; конечно, у каждого из них есть свои преимущества и недостатки.
**Реализация принципа**
.jpg)
**Механизм получения блокировки**
Поток пытается получить блокировку; если успешно — выполняется скрипт Lua, данные сохраняются в базе данных Redis.
Поток пытается получить блокировку; если неудачно — продолжает пытаться получить блокировку через цикл while; при успешном получении блокировки выполняется скрипт Lua, данные сохраняются в базе данных Redis.
**Автоматическое продление блокировки "Watch Dog"**
Это сложно понять, я нашёл некоторые материалы, но они также не объясняют это полностью. По моему мнению:
В распределённой среде, если поток получил блокировку, а затем сервер вышел из строя, блокировка будет автоматически освобождена через некоторое время. Вы можете установить время жизни блокировки (по умолчанию bcmath 30 секунд), чтобы предотвратить возникновение мёртвых замков.Поэтому здесь появляется "Watch Dog". Его задача заключается в том, что если поток 1 ещё не завершил выполнение бизнес-логики, а время истекло, поток 1 может запустить фоновый поток "Watch Dog", который будет постоянно продлевать время жизни ключа блокировки.**Внимание:** Обычно этот поток "Watch Dog" не запускается, и его запуск также может негативно повлиять на общую производительность, поэтому его не рекомендуется активировать.
**Почему использовать скрипт Lua?**
Это не требует многословия, если ваша бизнес-логика сложна, её можно упаковать в скрипт Lua и отправить в Redis. Так как Redis является однопоточным, это гарантирует атомарность выполнения этой сложной бизнес-логики.
Обычная распределённая блокировка Redis имеет определённые недостатки — она действует только на одном узле Redis. Если используется Sentinel и Cluster для обеспечения высокой доступности, и если мастер-узел из-за каких-либо причин перешёл в режим мастера-слейва, блокировка может быть потеряна:
Проблемы высокой доступности
Клиент 1 получил блокировку ресурса на Redis-узле-мастере.
При этом мастер вышел из строя, а ключ, хранящий информацию о блокировке, ещё не был синхронизирован на узел-слейве.
При переходе мастера в режим мастера-слейва и последующем выполнении процедуры failover, новый мастер-узел не будет иметь информации о блокировке.
Клиент 2 получает блокировку того же ресурса на новом мастере.
Таким образом, клиенты 1 и 2 одновременно владеют блокировкой одного и того же ресурса. Безопасность блокировки нарушена. Для решения этой проблемы Redis-автор antirez предложил алгоритм RedLock.
## 28. Недостатки распределённых блокировок Redis
Возможные проблемы высокой доступности:
1. Клиент 1 получил блокировку ресурса на Redis-узле-мастере.
2. При этом мастер вышел из строя, а ключ, хранящий информацию о блокировке, ещё не был синхронизирован на узел-слейве.
3. При переходе мастера в режим мастера-слейва и последующем выполнении процедуры failover, новый мастер-узел не будет иметь информации о блокировке.
4. Клиент 2 получает блокировку того же ресурса на новом мастере.
5. Таким образом, клиенты 1 и 2 одновременно владеют блокировкой одного и того же ресурса. Безопасность блокировки нарушена.Распределённые琐锁在 Redis 中可能会遇到一个问题,特别是在 Redis 哨兵模式下:
Клиент 1 записывает Redisson-лок на некоторый мастер-узел, затем данные асинхронно копируются на соответствующий slave-узел. Однако в процессе этого копирования, если мастер-узел выходит из строя и происходит переход на slave-узел, то клиент 2 может попытаться получить лок на новом мастер-узле. В этом случае несколько клиентов могут получить лок на один и тот же распределённый лок, что приведёт к проблемам в бизнес-логике и появлению грязных данных.
Недостаток проявляется в режиме работы с использованием sentinel или master-slave, когда при выходе из строя мастер-узла возможно получение лока несколькими клиентами одновременно.
Перевод:
Распределённые локи в Redis могут столкнуться с проблемой, особенно при использовании Redis в режиме с Sentinel:
Клиент 1 записывает Redisson-лок на определённый мастер-узел, после чего данные асинхронно копируются на соответствующий slave-узел. Однако во время этого копирования, если мастер-узел выходит из строя и происходит переход на slave-узел, то клиент 2 может попытаться получить лок на новом мастер-узле. В этом случае несколько клиентов могут получить лок на один и тот же распределённый лок, что приведёт к проблемам в бизнес-логике и появлению грязных данных.
Недостаток проявляется в режиме работы с использованием Sentinel или master-slave, когда при выходе из строя мастер-узла возможно получение лока несколькими клиентами одновременно.## 29. Принцип работы RedLock в Redis
RedLock — это распределённый лок, реализованный на основе Redis, который обеспечивает следующие характеристики:
**Мutual Exclusion**: В любое время только один клиент может владеть локом;
**Защита от deadlock**: Когда клиент получает лок, даже если произошло сетевое разделение или клиент вышел из строя, deadlock не возникнет; (используется время жизни ключа)
**Устойчивость**: Если большинство узлов Redis работают правильно, сервис будет доступен для использования, добавления или освобождения лока;
**Идея алгоритма RedLock**
Это означает, что лок не должен создаваться только на одном узле Redis, а должен создаваться на нескольких узлах Redis, **n / 2 + 1**, и только после успешного создания лока на большинстве узлов Redis можно считать, что RedLock был успешно создан, что позволяет избежать проблем, связанных с созданием лока только на одном узле Redis.
## 30. Четыре режима работы Redis
### 1) Одиночный режим
Установите и запустите один Redis, и он будет доступен для использования.
**Преимущества:**
- Простое развертывание, нулевые затраты.
- Низкие затраты, нет резервного узла, нет необходимости в дополнительных расходах.
- Высокая производительность, одиночному узлу не требуется синхронизация данных, естественная согласованность данных.
**Недостатки:**- Низкая надёжность, одиночный узел подвержен риску выхода из строя.
- Высокая производительность ограничена возможностями процессора, Redis работает в одном потоке.
Выбор одиночного режима зависит от конкретной бизнес-ситуации, если требуется высокая производительность и надёжность, одиночный режим может быть не самым подходящим решением.
### 2) Режим master-slave
Redis использует структуру развертывания с одним мастером и несколькими слейвами. Основное отличие от одиночного режима заключается в том, что данные между мастером и слейвами синхронизируются в реальном времени, и предоставляются стратегии сохранения данных и резервного копирования. Мастер и слейвы размещаются на разных физических серверах, и в зависимости от условий компании, можно обеспечить одновременный доступ к сервису и разделение нагрузки на чтение и запись.
#### Преимущества1. Высокая надежность: с одной стороны, использование двойной основной/резервной архитектуры позволяет автоматически переключаться на резервную систему при отказе основного сервера, обеспечивая непрерывную работу; с другой стороны, включение функции устойчивого хранения данных и правильной стратегии резервного копирования эффективно решает проблемы случайных ошибок и потери данных.
2. Стратегия разделения чтения и записи: узел-последователь может расширять способность основного узла к чтению, эффективно справляясь с большим количеством параллельных операций чтения.#### **Недостатки**1. Сложность восстановления после отказа: если отсутствует система RedisHA (требуется разработка), при отказе основного узла необходимо вручную превратить один узел-последователь в основной узел, уведомить сторону бизнеса о необходимости изменения конфигурации и заставить остальные узлы-последовательные копировать новый основной узел, что требует человеческого вмешательства и является сложным процессом.
2. Ограничение способности записи основного узла одним узлом: можно рассмотреть возможность шардинга.
3. Ограничение способности хранения основного узла одним узлом: можно рассмотреть использование Pika.Недостатки исходного репликационного механизма также проявляются в ранних версиях, например: при прекращении репликации Redis, Slave инициирует `psync`, если синхронизация не удастся, будет выполнена полная синхронизация, что может вызвать замедление на миллисекунды или секунды; из-за механизма COW в крайнем случае возможна переполнение памяти основного узла, что может привести к аварийному завершению программы или отказу; создание файлов резервного копирования основным узлом приводит к увеличению использования ресурсов I/O и процессора (для сжатия); отправка файлов резервного копирования размером в несколько гигабайт может вызвать увеличение пропускной способности выходного канала сервера, что может привести к блокировке запросов, рекомендуется обновиться до последней версии.#### Принцип репликации в главном и резервном узлах
Активное отправление со стороны резервного узла
После успешного запуска Slave и подключения к основному узлу, резервный узел отправляет команду sync. Основной узел получает команду и запускает фоновый процесс сохранения данных, собирая все команды, используемые для модификации данных. После завершения работы фонового процесса основной узел передает весь файл данных резервному узлу, завершая полную синхронизацию.
Полная синхронизация: после получения резервным узлом файла данных, он сохраняет его и загружает в память (при первом подключении резервного узла к основному).
Увеличенная синхронизация: основной узел продолжает передавать новые команды модификации данных резервному узлу по мере их сбора, завершая синхронизацию.
При повторном подключении после разрыва соединения, если это повторное подключение к основному узлу, будет автоматически выполнена полная синхронизация (полная синхронизация), и данные RDB будут переданы резервному узлу.
Основной узел отвечает за запись, резервный узел — за чтение.
### 3) Сентинел-модельRedis Sentinel — это нативное решение для обеспечения высокой доступности, введенное с версии 2.8. Архитектура его развертывания состоит из двух частей: кластера Redis Sentinel и кластера данных Redis. Кластер Redis Sentinel представляет собой распределенную систему, состоящую из нескольких узлов Sentinel, которые обеспечивают обнаружение отказов, автоматическое перенаправление отказов, центр конфигураций и уведомления клиентов. Количество узлов Redis Sentinel должно быть нечетным числом вида 2n+1 (n ≥ 1).**Преимущества:**
1. Простое развертывание кластера Redis Sentinel.
2. Решает проблему обеспечения высокой доступности при использовании режима master-slave Redis.
3. Легко реализуется линейное масштабирование узлов данных Redis, что позволяет легко преодолеть ограничения однопоточной архитектуры Redis, удовлетворяя потребности бизнеса в больших объемах данных или высокой производительности.
4. Можно использовать одну систему Sentinel для мониторинга одного или нескольких кластеров данных Redis.
**Недостатки:**
1. Развертывание относительно более сложное по сравнению с режимом master-slave Redis, принцип работы более сложен для понимания.
2. Нерациональное использование ресурсов, поскольку узлы slave в кластере данных Redis не предоставляют услуги.
3. Redis Sentinel предназначен в первую очередь для обеспечения высокой доступности узлов master в кластере данных Redis, а также для выявления отказов узлов данных Redis как subjective down и objective down. Для узлов slave Redis Sentinel выполняет только операцию subjective down, но не осуществляет перенаправление отказов.
4. Не решает проблему разделения чтения и записи, реализация более сложна.
### 4) Кластерная модельRedis Cluster — это решение для распределенного кластера Redis, введенное с версии 3.0. Оно предназначено для решения задач распределенного хранения данных Redis, таких как балансировка нагрузки при достижении ограничений по памяти, параллелизму и трафику. Минимальная конфигурация кластера Redis Cluster включает 6 узлов (3 master и 3 slave), где узлы master поддерживают операции чтения и записи, а узлы slave используются только для перенаправления отказов. Redis Cluster использует метод шардинга по слотам, все ключи отображаются на 16384 слота, каждый узел отвечает за обслуживание части этих слотов и связанных с ними данных.**Преимущества:**
1. Отсутствие центрального узла.
2. Данные хранятся по слотам на нескольких узлах, данные между узлами могут быть динамически перераспределены.
3. Линейное масштабирование до более чем 1000 узлов, узлы могут быть динамически добавлены или удалены.
4. Высокая доступность: кластер остаётся доступным даже при отказе части узлов. Увеличение количества Slave для создания резервной копии данных позволяет автоматически перенаправлять отказы. Узлы обмениваются информацией о состоянии через протокол сплетня, а переход Slave в Master осуществляется путём голосования.
5. Снижение затрат на эксплуатацию и повышение расширяемости и доступности системы.
**Недостатки:**1. Клиентская реализация сложна, требует реализации Smart Client, который кэширует информацию о сопоставлении слотов и своевременно обновляет её, что повышает сложность разработки. Недостаточная зрелость клиента влияет на стабильность бизнес-процессов. В настоящее время только JedisCluster считается относительно зрелым, однако обработка ошибок ещё несовершенна, например, часто встречающаяся "ошибка max redirect".
2. Узел может быть заблокирован по некоторым причинам (время блокировки превышает cluster-node-timeout), что приводит к его отключению. Такое переключение не всегда необходимо.
3. Данные передаются через асинхронное копирование, что не гарантирует сильной согласованности данных.
4. При использовании одной и той же кластерной конфигурации несколькими бизнес-приложениями невозможно эффективно разделить холодные и горячие данные на основе статистики, что снижает изоляцию ресурсов и увеличивает вероятность взаимного влияния.
5. Slave в кластере используется как "резерв", но не помогает снизить нагрузку на чтение. Однако можно оптимизировать использование ресурсов Slave за счёт рационального дизайна SDK.
6. Ограничения на массовые операции ключей, такие как mset и mget, поддерживаются только для ключей с одинаковым значением слота. Для ключей, отображаемых на различные слоты, операции mset, mget и sunion не поддерживаются.Ограниченная поддержка транзакций ключей, которая позволяет выполнять транзакции только для ключей, находящихся на одном узле. Когда ключи распределены между различными узлами, транзакционные операции невозможны.
8. Ключ является минимальной единицей для разделения данных, поэтому большие объекты данных, такие как хеш или список, не могут быть отображены на различные узлы.
9. Отсутствие поддержки нескольких пространств баз данных, хотя в одиночном режиме Redis поддерживает до OnClickListener.CLICK_MODE_DOWN 16 баз данных, в кластерном режиме доступно только одно пространство баз данных, то есть db 0.
10. Поддержка только одноуровневой структуры репликации, где отдельные узлы могут реплицироваться только от главного узла, что не допускает вложенной структуры репликации.
11. Избегайте создания hot-key, чтобы избежать того, что главный узел станет узким местом системы.
12. Избегайте создания big-key, чтобы избежать перегрузки сетевой карты и замедления запросов.
13. Время повторной попытки должно быть больше, чем cluster-node-time.
14. Redis Cluster не рекомендуется использовать для pipeline и многоключевых операций, чтобы минимизировать ситуации с ошибкой max redirect.## 31. Три режима кластеризации Redis
### 1) Основной-резервный
**Основной-резервный или основной-многорезервный**
Основной узел автоматически синхронизирует обновленные данные с резервными узлами посредством механизма master/slave, где основной узел предназначен для записи, а резервные узлы — для чтения.
Резервные узлы не могут выполнять операции записи.
Данные синхронизируются полностью между узлами.
Redis предоставляет функцию репликации (replication), которая позволяет автоматически синхронизировать обновленные данные одного узла с другими узлами.**Удовлетворение AP в CAP**
.jpg)
**Принцип работы**
При запуске базы данных-посредника она отправляет команду sync основной базе данных, которая начинает создание снимка RDB в фоновом режиме. Временные команды, полученные во время создания снимка, кэшируются. После завершения создания снимка основная база данных передает его вместе с кэшированными командами посреднику. Инициализация репликации завершена.
Затем основная база данных синхронно отправляет каждую команду посреднику. При возобновлении соединения после прерывания основная база данных версии 2.8 и выше передает команды, полученные во время прерывания, посреднику. Это называется увеличивающейся репликацией.Репликация основного и посредника является оптимистической, то есть когда клиент отправляет команду записи основному серверу, основной сервер немедленно возвращает результат клиенту и асинхронно отправляет команду посреднику, что не влияет на производительность. Также можно настроить минимальное количество посредников, которым должна быть отправлена команда, прежде чем основной сервер может записывать данные.
Бездисковая репликация: если производительность жесткого диска низкая, это может повлиять на производительность репликации. С версии 2.8 можно настроить бездисковую репликацию, repl-diskless-sync yes
#### 1) Один мастер и два посредника
Если мастер выходит из строя, выполните shutdown
Посредник `info replication` все еще показывает, что его мастером был вышедший из строя мастер
Если посредник выходит из строя, выполните shutdown
Мастер начинает запись данных, при запуске посредника он восстанавливает данные, начиная с самого начала
#### 2) Ответственный посредник
Когда мастер выходит из строя, последний посредник может немедленно стать мастером, его последующие посредники не требуют никаких изменений
Можно использовать команду: `slaveof no one` чтобы сделать посредника мастером
#### 3) Наследование ответственностиПоследний прокси-сервер может стать мастером для следующего прокси-сервера; прокси-сервер также может принимать соединения и запросы синхронизации от других прокси-серверов, таким образом этот прокси-сервер становится мастером для следующего звена цепочки, что эффективно снижает нагрузку записи на мастера и децентрализует риск.Старший брат посредника — это другой посредник.
Используйте `slaveof <ip> <port>`, чтобы изменить направление в процессе: будет очищено предыдущее состояние, и будет создан новый снимок.
Риск заключается в том, что если какой-то посредник выйдет из строя, последующие посредники не смогут восстановить данные.
Если мастер выходит из строя, посредник остаётся посредником и не может записывать данные.
### 2) Режим смотрителя
**Автоматическая версия ответственного посредника**, то есть способность мониторить основной сервер на наличие сбоев и автоматически конвертировать посредника в мастер при сбое.
### 3) Кластерный режим
**Режим смотрителя Redis уже обеспечивает высокую доступность и разделение чтения и записи**, но в этом режиме каждый сервер Redis хранит одинаковые данные, что очень расходует память. Поэтому в версии Redis 3.0 был добавлен режим кластера, который обеспечивает распределённое хранение Redis, то есть каждый узел Redis хранит разные данные. Redis-Cluster использует распределённую структуру без центрального узла, её особенности следующие:
Все узлы Redis взаимосвязаны (механизм PING-PONG), внутри используется двоичный протокол для оптимизации скорости передачи данных и пропускной способности.
Провал узла происходит тогда, когда более половины узлов в кластере обнаруживают его недоступность.Клиент подключается напрямую к узлу Redis, не требуя промежуточного агента. Клиенту требуется подключение только к одному доступному узлу из кластера.
#### Работа
На каждом узле Redis есть два элемента: слот (slot) с диапазоном значений от 0 до 16383 и кластер (cluster), который можно рассматривать как плагин управления кластером. Когда ключ для хранения или извлечения данных приходит, Redis вычисляет значение с помощью алгоритма CRC16 и затем берёт остаток от деления на 16384. Это позволяет каждому ключу соответствовать слоту с номером от 0 до 16383. Затем Redis использует это значение для определения соответствующего узла и автоматически переходит к нему для выполнения операций хранения или извлечения данных.
Для обеспечения высокой доступности в кластере Redis-Cluster используется режим master-slave. Один мастер соответствует одному или нескольким слейвам. Когда мастер становится недоступным, используется слейв. Когда другие мастера пингуют мастера A, если более половины мастеров не могут связаться с мастером A, считается, что мастер A недоступен. Если мастер A и его слейв A1 оба недоступны, кластер больше не может предоставлять услуги.
## 32. Девять типов данных в Redisstring: самый базовый тип данных, безопасная двоичная строка, **максимальный размер 512 МБ**.
list: последовательная строковая коллекция, сохраняющая порядок добавления.
set: неупорядоченная строковая коллекция, не допускающая повторений.
sorted set: упорядоченная строковая коллекция.
hash: коллекция пар ключ-значение.
bitmap: более детализированная операция, основанная на бите.
hyperloglog: вероятностная структура данных. # 2.8.9 добавлено
Geo: хранение географической информации и выполнение операций над ней # 3.2 добавлено
Stream: поток данных # 5.0 добавлено## 33. Применение типов данных в Redis
[Применение типов данных в Redis](https://blog.csdn.net/hudeyong926/article/details/99540705)
### 1) String строка
**Основные команды**
setnx, set, get, decr, incr, mget и т.д.
**Применение**
Строка является наиболее часто используемым типом данных, она может хранить любую строку, включая двоичные данные, JSON-объекты, даже Base64-кодированные изображения. В Redis максимальный размер строки составляет 512МБ, что делает её практически универсальной. **Ограничение на размер ключа и значения типа string в Redis составляет 512МБ**. - Кэш, горячие данные
- Распределенные сессии
- Распределенные блокировки
- INCR счетчики
- Число просмотров статьи, лайки в микроблогах, допускается некоторое запаздывание, данные сначала записываются в Redis, а затем периодически синхронизируются с базой данных
- Глобальный идентификатор
- Тип INT, INCRBY, использование атомарности
- Ограничение скорости INCR
- В качестве ключа используется IP-адрес посетителя и другие данные, при каждом доступе счетчик увеличивается, если превышено количество доступов, возвращается значение false.
- Управление битами через setbit
### **2) Хеш-таблица**
**Основные команды**
hget, hsetnx, hset, hvals, hgetall, hmset, hmget и другие.
## 34. Распределенная реализация Redis- Схема 1: SETNX + EXPIRE
- Схема 2: SETNX + значение (текущее время системы + время истечения)
- Схема 3: Использование скрипта Lua (включающего SETNX + EXPIRE)
- Схема 4: Расширенная команда SET (SET EX PX NX)
- Схема 5: SET EX PX NX + проверка уникального случайного значения, после чего освобождается блокировка
- Схема 6: Открытый фреймворк ~ Redisson
- Схема 7: Распределенная блокировка Redlock, реализованная на нескольких машинах
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )