Что делает Redis, когда заканчивается память?


111

Это может быть простой вопрос, но мне трудно найти ответ. Как Redis 2.0 справляется с нехваткой максимальной выделенной памяти? Как он решает, какие данные удалить или какие данные оставить в памяти?


Ответы:


94

Если у вас включена функция виртуальной памяти (я думаю, новая в версии 2.0 или 2.2), тогда Redis начинает сохранять «не так часто используемые» данные на диск, когда память заканчивается.

Если виртуальная память в Redis отключена, создается впечатление, что виртуальная память операционной системы начинает израсходоваться (например, подкачка), и производительность резко падает.

Теперь вы также можете настроить Redis с параметром maxmemory, который не позволяет Redis использовать больше памяти (по умолчанию).

В новых версиях Redis действуют различные политики при достижении maxmemory:

  • volatile-lru удаляет ключ из числа тех, у которых установлен срок действия, пытаясь удалить ключи, которые не использовались недавно.
  • volatile-ttl удаляет ключ среди ключей с установленным сроком действия, пытаясь удалить ключи с коротким оставшимся временем жизни.
  • volatile-random удаляет случайный ключ среди ключей с установленным сроком действия.
  • allkeys-lru похож на volatile-lru, но удаляет все типы ключей, как обычные, так и ключи с установленным сроком действия.
  • allkeys-random похож на volatile-random, но удаляет все виды ключей, как обычные, так и ключи с установленным сроком действия.

Если вы выберете политику, которая удаляет только ключи с установленным EXPIRE, тогда, когда Redis исчерпывает память, похоже, что программа просто прерывает операцию malloc (). То есть, если вы попытаетесь сохранить больше данных, операция просто потерпит неудачу.

Некоторые ссылки для получения дополнительной информации (так как вы не должны просто верить мне на слово):


8
Виртуальная память Redis устарела. См. Redis.io/topics/virtual-memory
cgaldiolo

19

Из redis.conf версии 2.8

# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU cache, or to set
# a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy volatile-lru

3
Значение по умолчанию maxmemory-policyв Redis 3.2 теперь noeviction: raw.githubusercontent.com/antirez/redis/3.2/redis.conf
LoicAG

5

Обновление Redis 4.0

127.0.0.1:6379> MEMORY HELP
1) "MEMORY DOCTOR                        - Outputs memory problems report"
2) "MEMORY USAGE <key> [SAMPLES <count>] - Estimate memory usage of key"
3) "MEMORY STATS                         - Show memory usage details"
4) "MEMORY PURGE                         - Ask the allocator to release memory"
5) "MEMORY MALLOC-STATS                  - Show allocator internal stats"

/usr/local/etc/redis.conf

############################## MEMORY MANAGEMENT ################################

# Set a memory usage limit to the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU or LFU cache, or to
# set a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction

# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can tune it for speed or
# accuracy. For default Redis will check five keys and pick the one that was
# used less recently, you can change the sample size using the following
# configuration directive.
#
# The default of 5 produces good enough results. 10 Approximates very closely
# true LRU but costs more CPU. 3 is faster but not very accurate.
#
# maxmemory-samples 5

4

Я только недавно начал читать о Redis, так что я не уверен. Но я обнаружил несколько лакомых кусочков, которые могут быть полезны.

Вот отрывок из http://antirez.com/post/redis-as-LRU-cache.html :

Еще один способ использования Redis в качестве кеша - это директива maxmemory, функция, которая позволяет указать максимальный объем используемой памяти. Когда новые данные добавляются на сервер и предел памяти уже достигнут, сервер удалит некоторые старые данные, удалив энергозависимый ключ, то есть ключ с установленным EXPIRE (тайм-аут), даже если до ключа еще далеко от автоматического истечения срока действия.

Кроме того, Redis 2.0 имеет режим виртуальной машины, в котором все ключи должны помещаться в памяти, но значения для редко используемых ключей могут быть на диске:


2

Если вам интересно, что на самом деле реагирует Redis (2.8), когда он достигает максимума, определенного его конфигурацией, это выглядит так:

$ redis-cli
127.0.0.1:6379> GET 5
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
127.0.0.1:6379> SET 5 a
(error) OOM command not allowed when used memory > 'maxmemory'.

1

Недавно у меня возникла ситуация с отсутствием свободной памяти, и мое приложение зависло (запись невозможна, чтение было возможно), выполнение сценариев PHP остановилось на полпути, и их пришлось kill -9вручную (даже после того, как память была сделал доступным).

Я предположил, что произошла потеря данных (или несогласованность данных), поэтому я сделал flushdbи восстановил из резервных копий. Урок выучен? Резервные копии - ваш друг.


-3

Redis не является кешем, как memcached, по умолчанию (где для maxmemory-policyпараметра установлено значение noeviction) все данные, которые вы помещаете в redis, не удаляются, единственное исключение - использование EXPIRE.


2
Так что же он делает, когда заканчивается память? Он просто будет хранить новые данные на диске, а не в памяти?
Кори

1
Это (сейчас) неверно, Redis имеет ключевой механизм выселения с несколькими доступными политиками: redis.io/topics/lru-cache
LoicAG

@LoicAG: Звучит совершенно правильно ... если нет политики истечения срока действия, Redis не будет выселять ключи. И это хорошо: я, например, не могу позволить Redis избавляться от ключей самостоятельно.
Майкл

@Cory: если настроена политика выселения, существующие ключи будут удалены. Однако, если вы не установили политику выселения, вы должны получить ошибку нехватки памяти.
Майкл

@Michael Полагаю, это вопрос терминологии: всегда существует политика maxmemory-policy, и по умолчанию действительно "noeviction"; но политики «allkeys-lru» и «allkeys-random» вытесняют ключи из всего набора, а другие («volatile- *») вытесняют ключи из подмножества ключей, для которых определен TTL.
LoicAG
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.