предисловие
Как сервер, память не безгранична, поэтому всегда будет исчерпание памяти, поэтому, когдаRedis
После исчерпания памяти сервера, если вы продолжите выполнять команду запроса,Redis
Как это будет обрабатываться?
восстановление памяти
использоватьRedis
Во многих случаях при обслуживании некоторые пары ключ-значение действительны только в течение определенного периода времени.Чтобы данные этого типа не занимали память все время, мы можем установить период действия для пар ключ-значение.Redis
сквозь4
Отдельная команда для установки срока действия ключа:
-
expire key ttl
:будетkey
Срок действия значения установлен наttl
второй. -
pexpire key ttl
:будетkey
Срок действия значения установлен наttl
миллисекунда. -
expireat key timestamp
:будетkey
Срок действия значения устанавливается равным указанномуtimestamp
секунды. -
pexpireat key timestamp
:будетkey
Срок действия значения устанавливается равным указанномуtimestamp
миллисекунды.
PS: Независимо от того, какая команда используется, в концеRedis
Нижний слой используетсяpexpireat
команда для достижения. Кроме того,set
Команды также могут быть установленыkey
В то же время добавьте время истечения, что может обеспечить атомарность установки значения и установки времени истечения.
После установки срока действия можно пройтиttl
иpttl
Две команды для запроса оставшегося времени истечения срока действия (если срок действия не установлен, следующие две команды возвращают-1
, если установлено недопустимое время истечения, оба возвращают-2
):
-
ttl key
возвращениеkey
Оставшиеся истекшие секунды. -
pttl key
возвращениеkey
Количество миллисекунд, оставшихся до истечения срока действия.
Политика истечения срока действия
Если ключ с истекшим сроком действия удален, у нас обычно есть три стратегии:
- Удаление по времени: установите таймер для каждого ключа, и по истечении срока действия ключ будет удален. Эта стратегия удобна для памяти, но
CPU
Не дружелюбно, потому что каждый таймер занимает определенное количествоCPU
ресурс. - Ленивое удаление: независимо от того, истек срок действия ключа или нет, он не будет активно удален.Он будет ждать, пока каждый раз не получит ключ, чтобы определить, истек ли срок его действия.Если срок его действия истек, удалите ключ, в противном случае верните соответствующее значение к ключу. Эта стратегия не является дружественной к памяти и может привести к потере большого количества памяти.
- Периодическое сканирование: система регулярно сканирует через равные промежутки времени и удаляет все ключи с истекшим сроком действия, если они найдены. Эта стратегия представляет собой относительно компромисс между двумя вышеуказанными стратегиями.Следует отметить, что регулярная частота должна контролироваться в соответствии с реальной ситуацией.Одним из недостатков использования этой стратегии является то, что ключи с истекшим сроком действия также могут быть возвращены.
существуетRedis
Среди них он выбирает стратегию2
и стратегия3
комплексное использование. ноRedis
При периодическом сканировании будут сканироваться только ключи с установленным сроком действия, поскольку ключи с установленным сроком действияRedis
хранятся отдельно, поэтому нет возможности отсканировать все ключи:
typedef struct redisDb {
dict *dict; //所有的键值对
dict *expires; //设置了过期时间的键值对
dict *blocking_keys; //被阻塞的key,如客户端执行BLPOP等阻塞指令时
dict *watched_keys; //WATCHED keys
int id; //Database ID
//... 省略了其他属性
} redisDb;
8 стратегий устранения
еслиRedis
Все ключи не просрочены, и память в это время заполнена, тогда клиент продолжает выполнениеset
Пока жду заказRedis
Как это будет обрабатываться?Redis
Для этого сценария предусмотрены различные стратегии устранения.
во-первыхRedis
предоставил параметрmaxmemory
настроитьRedis
Максимально используемая память:
maxmemory <bytes>
Или вы также можете использовать командуconfig set maxmemory 1GB
Динамически изменен.
Если этот параметр не задан, то32
разрядная операционная системаRedis
наиболее используемый3GB
памяти, находясь в64
Ограничений в операционной системе бит нет.
Redis
предоставлено в8
Тип вне политики, параметры могут бытьmaxmemory-policy
Чтобы настроить:
стратегия устранения | инструкция |
---|---|
volatile-lru | Удаляйте ключи со сроком действия, установленным в соответствии с алгоритмом LRU, пока не освободится место. Если ключевой объект для удаления отсутствует, а памяти по-прежнему недостаточно, сообщается об ошибке |
allkeys-lru | Удаляйте все ключи по алгоритму LRU, пока не освободится место. Если ключевой объект для удаления отсутствует, а памяти по-прежнему недостаточно, сообщается об ошибке |
volatile-lfu | Ключи с установленным сроком действия удаляются по алгоритму LFU до тех пор, пока не освободится место. Если ключевой объект для удаления отсутствует, а памяти по-прежнему недостаточно, сообщается об ошибке |
allkeys-lfu | Все ключи удаляются по алгоритму LFU, пока не освободится место. Если ключевой объект для удаления отсутствует, а памяти по-прежнему недостаточно, сообщается об ошибке |
volatile-random | 随机删除设置了过期时间的键,直到腾出可用空间。 Если ключевой объект для удаления отсутствует, а памяти по-прежнему недостаточно, сообщается об ошибке |
allkeys-random | Случайным образом удаляйте все ключи, пока не освободится место. Если ключевой объект для удаления отсутствует, а памяти по-прежнему недостаточно, сообщается об ошибке |
volatile-ttl | В соответствии со свойством ttl объекта «ключ-значение» удалите данные, срок действия которых истекает недавно. Если нет, сообщите об ошибке напрямую |
noeviction | Стратегия по умолчанию без какой-либо обработки сообщает об ошибке напрямую |
PS: стратегия исключения также может использовать команду напрямуюconfig set maxmemory-policy <策略>
для динамической конфигурации.
Алгоритм LRU
LRU
Полное имя:Least Recently Used
. То есть: в последнее время он давно не использовался. Это в основном для времени использования.
Redis улучшил алгоритм LRU
существуетRedis
Среди них традиционныеLRU
алгоритм, так как традиционныйLRU
Алгоритмы существуют2
вопросы:
- Для хранения требуется дополнительное место.
- могут быть некоторые
key
Значение используется часто, но в последнее время не использовалось, поэтомуLRU
Алгоритм удаления.
Чтобы избежать вышеперечисленного2
Проблема,Redis
среди традиционныхLRU
Алгоритм изменен,удалить путем выборки.
Свойство предоставляется в файле конфигурацииmaxmemory_samples 5
, значение по умолчанию5
, указывает на случайное извлечение5
Кусокkey
значение, то5
Кусокkey
стоимость согласноLRU
алгоритм удаления, так что очевидно,key
Чем больше значение, тем точнее удаление.
ВыборкаLRU
Алгоритм и традиционныйLRU
алгоритм,Redis
На официальном сайте есть сравнительная таблица:
-
Светло-серые полосы — это удаленные объекты.
-
Серые полосы — это объекты, которые не были удалены.
-
Зеленый — добавленный объект.
Первая картинка в верхнем левом углу представляет собой традиционнуюLRU
алгоритма видно, что когда количество выборок достигает10
(вверху справа), уже и традиционныеLRU
Алгоритм очень близкий.
Как Redis управляет данными о тепле
Когда мы говорили о строковых объектах ранее, мы упомянулиredisObject
объект существует вlru
Атрибуты:
typedef struct redisObject {
unsigned type:4;//对象类型(4位=0.5字节)
unsigned encoding:4;//编码(4位=0.5字节)
unsigned lru:LRU_BITS;//记录对象最后一次被应用程序访问的时间(24位=3字节)
int refcount;//引用计数。等于0时表示可以被垃圾回收(32位=4字节)
void *ptr;//指向底层实际的数据存储结构,如:SDS等(8字节)
} robj;
lru
Свойство создается при записи объекта, оно будет обновляться при доступе к объекту. Нормальная идея заключается в том, что окончательное решение о том, следует ли удалять ключ, должно быть вычтено из текущей временной метки.lru
, тот, у которого разница больше, будет удален первым. ноRedis
Это не то, что он делает там,Redis
Глобальное свойство поддерживается вlru_clock
, это свойство передается через глобальную функциюserverCron
любой другой100
Он обновляется один раз в миллисекунду, и запись является текущей.unix
метка времени.
Окончательное решение об удалении данных принимается черезlru_clock
минус объектlru
производные от свойств. так почемуRedis
Сделать это? Не более ли точно брать глобальное время напрямую?
Это связано с тем, что это позволяет избежать обновления объекта каждый раз.lru
Когда атрибут используется, глобальный атрибут может быть получен напрямую без вызова системной функции для получения системного времени, тем самым повышая эффективность (Redis
Есть много из этой детализации для повышения производительности, что можно сказать, что можно оптимизировать до максимально возможной).
Но тут есть проблема, мы видим,redisObject
в объектеlru
только собственность24
немного,24
биты могут храниться только194
Размер временной метки в днях после превышения194
Через несколько дней он перезапустится с0
начать считать, так что это время может появитьсяredisObject
в объектеlru
Свойства больше, чем глобальныеlru_clock
ситуация с недвижимостью.
Из-за этого расчет также необходимо разделить на2
кейс:
- Когда глобал
lruclock
>lru
, затем используйтеlruclock
-lru
Получите свободное время. - когда глобальный
lruclock
<lru
, затем используйтеlruclock_max
(который194
небо) -lru
+lruclock
Получите свободное время.
Следует отметить, что этот метод расчета не гарантирует, что самое длинное время простоя можно удалить из выборочных данных. Это потому, что в первую очередь194
Дни используются пока редко, опять же толькоlruclock
первое2
раунды продолжают превышатьlru
Атрибуты, расчет будет проблемой.
например объектA
записаноlru
да1
дней, покаlruclock
Второй раунд10
Боже, в это время результат расчета будет только10-1=9
Боже, это должно быть на самом деле194+10-1=203
небо. Однако такая ситуация, можно сказать, встречается реже, поэтому данный метод обработки может иметь неточные удаления, но сам по себе этот алгоритм является приблизительным алгоритмом, поэтому большого влияния он не окажет.
LFU-алгоритм
LFU
Полное имя:Least Frequently Used
. То есть: наименее частое использование в последнее время, это в основном для частоты использования. Это свойство также задокументировано вredisObject
серединаlru
Собственность внутри.
когда мы принимаемLFU
При стратегии утилизацииlru
высокий атрибут16
Бит используется для записи времени доступа (время последнего уменьшения: ldt, в минутах), низкий8
Биты используются для записи частоты доступа (логистический счетчик: LOGC), упомянутой кcounter
.
Частота доступа увеличивается
LFU
Счетчик только на ключ8
бит, максимальное значение, которое он может представлять, равно255
,такRedis
реализуется с использованием вероятностного логарифмаcounter
的递增。 р
Учитывая старую частоту доступа, при доступе к ключуcounter
Увеличение следующим образом:
- извлекать
0
и1
случайное число междуR
. -
counter
- начальное значение (по умолчанию5
), получить базовую разницу, если разница меньше0
, то сразу взять0
, для удобства расчета эта разница записывается какbaseval
. - вероятность
P
Формула расчета:1/(baseval * lfu_log_factor + 1)
. - если
R < P
, приращение частоты (counter++
).
в формулеlfu_log_factor
называется логарифмическим коэффициентом, значение по умолчанию равно10
, которым можно управлять с помощью параметров:
lfu_log_factor 10
На следующем рисунке показан логарифмический коэффициентlfu_log_factor
И частотаcounter
График роста:
Видно, что при логарифмическом множителеlfu_log_factor
за100
когда, наверное10M(1000万)
посещения будутcounter
увеличить до255
, а по умолчанию10
также может поддерживать1M(100万)
посещенияcounter
достигать255
Верхний предел, достаточный для большинства сценариев.
снижение частоты
Если частота посещенияcounter
Просто были повышения, так поздно, я получу все.255
, Этоcounter
Он увеличивается и не может полностью реагировать на одинkey
жара, поэтому, когда определеннаяkey
После периода бездействия,counter
Также требуется соответствующее сокращение.
counter
Скорость снижения определяется параметромlfu-decay-time
управления, по умолчанию1
, в минутах. По умолчанию1
Выражать:N
Нет доступа в минутах,counter
вот-вот уменьшитсяN
.
lfu-decay-time 1
Конкретный алгоритм выглядит следующим образом:
- Получите текущий отметку времени вминутаПринять низко после
16
бит (для удобства последующих вычислений это значение записывается какnow
). - удалить объект
lru
высокие атрибуты16
бит (для удобства последующих вычислений это значение записывается какldt
). - когда
lru
>now
, по умолчанию истек один цикл (16
бит, макс.65535
), то возьмите разницу65535-ldt+now
:когдаlru
<=now
, возьми разницуnow-ldt
(Для удобства последующих расчетов эта разница записывается какidle_time
). - Выньте файл конфигурации
lfu_decay_time
значение, затем рассчитать:idle_time / lfu_decay_time
(Для удобства последующих расчетов это значение записывается какnum_periods
). - наконец
counter
уменьшать:counter - num_periods
.
Это выглядит так сложно, но формула расчета на самом деле состоит из одного предложения: выньте текущую временную метку иlru
Сравните атрибуты и подсчитайте, как долго к ним не обращались.Например, вычисленный результат100
минут не было доступа до удаления параметра конфигурацииlfu_decay_time
Если эта конфигурация по умолчанию1
это100/1=100
,представлять100
минут без доступа, поэтомуcounter
просто уменьшить100
.
Суммировать
Эта статья в основном знакомитRedis
Срок действия ключа политики обработки истек, и когда памяти сервера недостаточноRedis
из8
стратегия устранения, и, наконец, введенаRedis
Два основных алгоритма исключения вLRU
иLFU
.