¿Qué hace Redis cuando se queda sin memoria?

111

Esta puede ser una pregunta fácil, pero me está costando encontrar la respuesta. ¿Cómo maneja Redis 2.0 quedarse sin memoria máxima asignada? ¿Cómo decide qué datos eliminar o qué datos guardar en la memoria?

Cory
fuente

Respuestas:

94

Si tiene la funcionalidad de memoria virtual activada (creo que es nueva en la versión 2.0 o 2.2), entonces Redis comienza a almacenar los datos "que no se usan con tanta frecuencia" en el disco cuando la memoria se agota.

Si la memoria virtual en Redis está deshabilitada, parece que la memoria virtual del sistema operativo comienza a agotarse (es decir, intercambia) y el rendimiento cae enormemente.

Ahora, también puede configurar Redis con un parámetro maxmemory, que evita que Redis use más memoria (el predeterminado).

Las versiones más recientes de Redis tienen varias políticas cuando se alcanza maxmemory:

  • volatile-lru elimina una clave entre las que tienen un vencimiento establecido, tratando de eliminar las claves que no se han utilizado recientemente.
  • volatile-ttl elimina una clave entre las que tienen un conjunto de expiración, tratando de eliminar las claves con poco tiempo de vida restante.
  • volatile-random elimina una clave aleatoria entre las que tienen un conjunto de expiración.
  • allkeys-lru como volatile-lru, pero eliminará todo tipo de clave, tanto las claves normales como las claves con un conjunto de expiración.
  • allkeys-random como volatile-random, pero eliminará todo tipo de claves, tanto las claves normales como las claves con caducidad.

Si elige una política que solo elimina claves con un EXPIRE establecido, cuando Redis se queda sin memoria, parece que el programa simplemente aborta la operación malloc (). Es decir, si intenta almacenar más datos, la operación simplemente falla estrepitosamente.

Algunos enlaces para obtener más información (ya que no debería creer en mi palabra):

BMiner
fuente
8
La memoria virtual de Redis ahora está en desuso. Ver redis.io/topics/virtual-memory
cgaldiolo
19

Desde redis.conf , versión 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
daniel__
fuente
3
El valor predeterminado maxmemory-policyen Redis 3.2 ahora es noeviction: raw.githubusercontent.com/antirez/redis/3.2/redis.conf
LoicAG
5

Actualización de 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
Oshaiken
fuente
4

Recientemente comencé a leer sobre Redis, así que no estoy seguro. Pero encontré algunas cositas que pueden ser útiles.

Aquí hay un fragmento de http://antirez.com/post/redis-as-LRU-cache.html :

Otra forma de usar Redis como caché es la directiva maxmemory, una característica que permite especificar una cantidad máxima de memoria a usar. Cuando se agregan nuevos datos al servidor y ya se alcanzó el límite de memoria, el servidor eliminará algunos datos antiguos eliminando una clave volátil, es decir, una clave con un EXPIRE (un tiempo de espera) establecido, incluso si la clave aún está lejos caduque automáticamente.

Además, Redis 2.0 tiene un modo VM en el que todas las claves deben caber en la memoria, pero los valores de las claves que se usan con poca frecuencia pueden estar en el disco:

12 revoluciones
fuente
2

Si te preguntas qué responde realmente Redis (2.8) cuando alcanza el máximo definido por su configuración, se ve así:

$ 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'.
Lukáš Lánský
fuente
1

Recientemente experimenté una situación de falta de memoria libre y mi aplicación se detuvo (no es posible escribir, leer), la ejecución de scripts PHP se detuvo en seco a mitad de camino y tuve que kill -9hacerla manualmente (incluso después de que se eliminó la memoria). Hecho disponible).

Supuse que se había producido una pérdida de datos (o inconsistencia de datos), así que hice una flushdby restauré desde las copias de seguridad. ¿Lección aprendida? Las copias de seguridad son tus amigas.

Adrian
fuente
-3

Redis no es un caché como memcached, de forma predeterminada (donde el maxmemory-policyparámetro está configurado en noeviction) no se eliminarán todos los datos que coloque en redis, la única excepción es el uso de EXPIRE.

Tobias P.
fuente
2
Entonces, ¿qué hace cuando se queda sin memoria? ¿Solo almacenará nuevos datos en el disco, no en la memoria?
Cory
1
Esto es (ahora) incorrecto, Redis tiene un mecanismo de desalojo clave, con varias políticas disponibles: redis.io/topics/lru-cache
LoicAG
@LoicAG: Me suena perfectamente correcto ... a menos que haya una política de expropiación, Redis no desalojará ninguna llave. Y eso es bueno: yo, por ejemplo, no puedo permitirme que Redis se deshaga de las claves por sí solo.
Michael
@Cory: si hay una política de desalojo configurada, eliminará las claves existentes. Sin embargo, si no estableció ninguna política de desalojo, debería recibir un error de memoria insuficiente.
Michael
@Michael Supongo que es una cuestión de terminología: siempre hay una política de memoria máxima, y ​​el valor predeterminado es "noeviction"; pero las políticas "allkeys-lru" y "allkeys-random" desalojan las claves de todo el conjunto, y las otras ("volatile- *") desalojan las claves del subconjunto de claves que tienen un TTL definido.
LoicAG