Вопросы и краткие ответы
Redis
Введение в Redis
Redis — это высокопроизводительная система хранения данных key-value. Она способна выполнять до 100 000 и более операций в секунду (QPS).
Основные характеристики Redis
- Поддержка сохранения данных на диск, что позволяет загружать данные из памяти обратно после перезапуска.
- Поддержка различных типов данных, включая ключ-значение, а также другие сложные структуры данных.
- Поддержка резервного копирования данных, то есть режима master-slave.
Какие структуры данных поддерживает Redis
- STRING: строка, целое число или число с плавающей точкой.
- LIST: список, который может хранить несколько одинаковых строк.
- SET: множество, которое хранит различные элементы без учета порядка.
- HASH: хэш-таблица, которая хранит отображение ключ-значение без учета порядка.
- ZSET: отсортированное множество, которое хранит ключ-значение, упорядоченное по ключу.
Различия между Redis и Memcache
Параметр |
Redis |
Memcache |
Типы данных |
Разнообразные типы данных |
Только простые ключ-значение |
Консистентность данных |
Транзакции |
CAS |
Устойчивость данных |
Снимок/AOF |
Нет |
Сетевой ввод/вывод |
Однопоточный ввод/вывод |
Многопоточный, асинхронный ввод/вывод |
Управление памятью |
Запрос памяти на месте |
Предварительное выделение памяти |
Публикация и подписка Публикация и подписка (pub/sub) — это модель обмена сообщениями: отправитель (pub) отправляет сообщения, а получатель (sub) получает их.
Стратегии сохранения данных
Сохранение данных с помощью снимков
Сохранение всех данных в определенный момент времени на диск. Используется команда BGSAVE
, которая может вызвать длительное простоя системы при увеличении объема используемой памяти.
Сохранение данных с помощью AOF
Запись всех команд записи в файл. Используется при использовании стратегии AOF, которая требует большого количества записей на диск, что может ограничить производительность Redis из-за производительности диска.
Транзакции Redis
redis> MULTI # Отметка начала транзакции
OK
redis> INCR user_id # Команды добавляются в очередь
QUEUED
redis> INCR user_id
QUEUED
redis> INCR user_id
QUEUED
redis> PING
QUEUED
redis> EXEC # Выполнение
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG
В случае Redis, если одна из команд в транзакции не выполнена, остальные команды все равно будут выполнены. Команда DISCARD отменяет транзакцию и отказывается выполнять все команды внутри блока транзакции.
Как реализовать распределенные блокировки
Метод 1
tryLock() {
SETNX Key 1 Seconds
}
release() {
DELETE Key
}
Недостаток: если C1 выполняется слишком долго и не освобождает блокировку, C2 может получить блокировку после истечения времени блокировки C1.В этом случае C1 и C2 могут выполняться одновременно, что может привести к несоответствию данных и другим неизвестным проблемам. Если C1 завершит выполнение первым, то он освободит блокировку C2, что может привести к тому, что C3 получит блокировку.
Вариант 2
tryLock() {
SETNX Key UnixTimestamp Seconds
}
release() {
EVAL (
--LuaScript
if redis. call("get", KEYS[1]) == ARGV[1] then
return redis. call("del", KEYS[1])
else
return 0
end
)
}
Недостаток: в условиях высокой конкуренции (например, при раздаче红包), может возникнуть проблема с повторением UnixTimestamp. В распределённой среде физическая синхронизация часов также не гарантируется, что может привести к повторению UnixTimestamp.
Вариант 3
tryLock() {
SET Key UniqId Seconds
}
release() {
EVAL (
--LuaScript
if redis. call("get", KEYS[1]) == ARGV[1] then
return redis. call("del", KEYS[1])
else
return 0
end
)
}
Эффект выполнения SET key value NX
эквивалентен выполнению SETNX key value
.
На данный момент это оптимальный вариант распределённой блокировки, но он всё ещё имеет проблемы при работе в кластере. Из-за асинхронной синхронизации данных Redis, если блокировка была получена на узле Master до завершения синхронизации данных, и узел Master выйдет из строя, новый узел Master всё ещё сможет получить блокировку, что приведёт к получению блокировки несколькими клиентами одновременно. ### Стратегии истечения срока действия и механизмы отсеивания Redis
Стратегии истечения срока действия
Стратегии истечения срока действия Redis определяют, как Redis обрабатывает ключи, истёкшие срок действия.
- Временная стратегия: для каждого ключа с истёкшим сроком действия создаётся таймер, который немедленно удаляет ключ при истечении срока. Эффективно по использованию памяти, но неэффективно по использованию процессора.
- Ленивая стратегия: при доступе к ключу проверяется истечение срока действия, и ключ удаляется при истечении срока. Эффективно по использованию процессора, но неэффективно по использованию памяти.
- Регулярная стратегия: периодически проверяется словарь expires, и удаляются истёкшие срок действия ключи. Эффективно по использованию памяти и процессора.
Механизмы отсеивания
[root]# redis-cli config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
- noeviction: новые записи будут отклонены.
- allkeys-lru: удаляются ключи, которые наименее часто используются.
- allkeys-random: случайным образом удаляются некоторые ключи.
- volatile-lru: удаляются ключи, которые наименее часто используются среди ключей с истёкшим сроком действия.
- volatile-random: случайным образом удаляются некоторые ключи среди ключей с истёкшим сроком действия.
- volatile-ttl: удаляются ключи с истёкшим сроком действия, у которых ближайшее истечение срока действия. ### Почему Redis является однопоточным
Redis основывается на операциях в памяти, поэтому CPU не является бутылочным горлышком для Redis. Бутылочным горлышком для Redis наиболее вероятно будет являться память или сеть. Кроме того, использование однопоточного режима легко реализуемо, что позволяет избежать необязательных переключений контекста и конкуренции за ресурсы, а также не требует затрат на переключение потоков.### Как использовать многоядерные процессоры
В случае одного экземпляра на одном сервере, если все операции имеют сложность O(N) или O(log(N)), потребление CPU не будет слишком высоким. Для максимального использования CPU на одном сервере можно развернуть несколько экземпляров Redis.### Методы реализации команд для множеств
| Команда | Метод реализации для intset кодирования | Метод реализации для hashtable кодирования |
| --- | --- | --- |
| SADD | Вызов функции intsetAdd для добавления всех новых элементов в целочисленное множество | Вызов функции dictAdd для добавления пары ключ-значение (где ключ — новый элемент, а значение — NULL) в хэш-таблицу |
| SCARD | Вызов функции intsetLen для возврата количества элементов в целочисленном множестве | Вызов функции dictSize для возврата количиества пар ключ-значение в хэш-таблице |
| SISMEMBER | Вызов функции intsetFind для поиска заданного элемента в целочисленном множестве | Вызов функции dictFind для поиска заданного элемента в ключах хэш-таблицы |
| SMEMBERS | Перебор всего целочисленного множества с использованием функции intsetGet для возврата элементов множества | Перебор всего хэш-таблицы с использованием функции dictGetKey для возврата ключей хэш-таблицы |
| SRANDMEMBER | Вызов функции intsetRandom для случайного выбора элемента из целочисленного множества | Вызов функции dictGetRandomKey для случайного выбора ключа из хэш-таблицы |
| SPOP | Вызов функции intsetRandom для случайного выбора элемента из целочисленного множества, затем удаление этого элемента с помощью функции intsetRemove | Вызов функции dictGetRandomKey для случайного выбора ключа из хэш-таблицы, затем удаление этого ключа с помощью функции dictDelete || SREM | Вызов функции intsetRemove для удаления всех заданных элементов из целочисленного множества | Вызов функции dictDelete для удаления всех пар ключ-значение, где ключ — заданный элемент |### Методы реализации команд для упорядоченных множеств
| Команда | Метод реализации для ziplist кодирования | Метод реализации для zset кодирования |
| --- | --- | --- |
|ZADD|Вызывает функцию ziplistInsert, чтобы вставить элемент и его рейтинг как два узла в сжатый список|Сначала вызывает функцию zslInsert, чтобы добавить новый элемент в скип-лист, затем вызывает функцию dictAdd, чтобы связать новый элемент с словарем|
|ZCARD|Вызывает функцию ziplistLen, чтобы получить количество узлов в сжатом списке, а затем делит это количество на 2, чтобы получить количество элементов в множестве|Доступ к свойству length структуры данных skip-list, чтобы получить количество элементов в множестве|
|ZCOUNT|Проходит по сжатому списку, подсчитывая количество узлов, чьи рейтинги находятся в заданном диапазоне|Проходит по скип-листу, подсчитывая количество узлов, чьи рейтинги находятся в заданном диапазоне|
|ZRANGE|Проходит по сжатому списку от начала к концу, возвращая все элементы в заданном диапазоне индексов|Проходит по скип-листу от начала к концу, возвращая все элементы в заданном диапазоне индексов|
|ZREVRANGE|Проходит по сжатому списку от конца к началу, возвращая все элементы в заданном диапазоне индексов|Проходит по скип-листу от конца к началу, возвращая все элементы в заданном диапазоне индексов||ZRANK|Проходит по сжатому списку от начала до конца, ищет заданный элемент, по пути подсчитывая количество узлов. Когда заданный элемент найден, количество узлов по пути равно рангу элемента|Проходит по скип-листу от начала до конца, ищет заданный элемент, по пути подсчитывая количество узлов. Когда заданный элемент найден, количество узлов по пути равно рангу элемента|
|ZREVRANK|Проходит по сжатому списку от конца до начала, ищет заданный элемент, по пути подсчитывая количество узлов. Когда заданный элемент найден, количество узлов по пути равно рангу элемента|Проходит по скип-листу от конца до начала, ищет заданный элемент, по пути подсчитывая количество узлов. Когда заданный элемент найден, количество узлов по пути равно рангу элемента|
|ZREM|Проходит по сжатому списку, удаляет все узлы, содержащие заданный элемент, а также узлы рейтинга, расположенные рядом с узлами элемента|Проходит по скип-листу, удаляет все узлы, содержащие заданный элемент, а также удаляет связь между элементом и его рейтингом из словаря|
|ZSCORE|Проходит по сжатому списку, находит узел, содержащий заданный элемент, затем находит узел рейтинга, расположенный рядом с узлом элемента, и сохраняет значение рейтинга|Прямой доступ к рейтингу заданного элемента из словаря|
redis.conf конфигурация
медленные запросы
Опубликовать ( 0 )