Que fait Redis lorsqu'il manque de mémoire?


111

C'est peut-être une question facile, mais j'ai du mal à trouver la réponse. Comment Redis 2.0 gère-t-il le manque de mémoire allouée maximale? Comment décide-t-il quelles données supprimer ou quelles données conserver en mémoire?


Réponses:


94

Si vous avez activé la fonctionnalité de mémoire virtuelle (nouveau dans la version 2.0 ou 2.2, je pense), Redis commence à stocker les données "pas si fréquemment utilisées" sur le disque lorsque la mémoire est épuisée.

Si la mémoire virtuelle dans Redis est désactivée, il semble que la mémoire virtuelle du système d'exploitation commence à s'épuiser (c.-à-d. Swap), et les performances diminuent considérablement.

Désormais, vous pouvez également configurer Redis avec un paramètre maxmemory, qui empêche Redis d'utiliser plus de mémoire (par défaut).

Les nouvelles versions de Redis ont diverses politiques lorsque la mémoire maximale est atteinte:

  • volatile-lru supprime une clé parmi celles dont le jeu expire, en essayant de supprimer les clés non utilisées récemment.
  • volatile-ttl supprime une clé parmi celles dont le jeu expire, en essayant de supprimer les clés avec peu de temps restant à vivre.
  • volatile-random supprime une clé aléatoire parmi celles dont le jeu expire.
  • allkeys-lru comme volatile-lru, mais supprimera tous les types de clés, à la fois les clés normales ou les clés avec un jeu d'expiration.
  • allkeys-random comme volatile-random, mais supprimera tous les types de clés, à la fois les clés normales et les clés avec un jeu d'expiration.

Si vous choisissez une stratégie qui supprime uniquement les clés avec un ensemble EXPIRE, alors lorsque Redis manque de mémoire, il semble que le programme abandonne simplement l'opération malloc (). Autrement dit, si vous essayez de stocker plus de données, l'opération échoue lamentablement.

Quelques liens pour plus d'informations (puisque vous ne devriez pas me croire sur parole):


8
La mémoire virtuelle Redis est désormais obsolète. Voir redis.io/topics/virtual-memory
cgaldiolo

19

À partir de redis.conf , version 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
La valeur maxmemory-policypar défaut dans Redis 3.2 est maintenant noeviction: raw.githubusercontent.com/antirez/redis/3.2/redis.conf
LoicAG

5

Mettre à jour 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

J'ai récemment commencé à lire sur Redis, donc je ne suis pas sûr. Mais, je suis tombé sur quelques bribes qui peuvent être utiles.

Voici un extrait de http://antirez.com/post/redis-as-LRU-cache.html :

Une autre façon d'utiliser Redis comme cache est la directive maxmemory, une fonctionnalité qui permet de spécifier une quantité maximale de mémoire à utiliser. Lorsque de nouvelles données sont ajoutées au serveur et que la limite de mémoire a déjà été atteinte, le serveur supprimera certaines anciennes données en supprimant une clé volatile, c'est-à-dire une clé avec un EXPIRE (un timeout) défini, même si la clé est encore loin d'expirer automatiquement.

De plus, Redis 2.0 a un mode VM où toutes les clés doivent tenir en mémoire, mais les valeurs des clés rarement utilisées peuvent être sur le disque:


2

Si vous vous demandez ce que Redis (2.8) répond réellement lorsqu'il atteint le maximum défini par sa configuration, cela ressemble à ceci:

$ 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

J'ai récemment vécu une situation sans mémoire libre et mon application s'est arrêtée (les écritures ne sont pas possibles, les lectures étaient possibles), l'exécution de scripts PHP s'est arrêtée à mi-chemin et a dû être kill -9manuellement (même après que la mémoire était mise à disposition).

J'ai supposé qu'une perte de données (ou une incohérence des données) s'était produite, alors j'ai fait une flushdbet restauré à partir de sauvegardes. Leçon apprise? Les sauvegardes sont votre ami.


-3

Redis n'est pas un cache comme memcached, par défaut (où le maxmemory-policyparamètre est défini sur noeviction) toutes les données que vous mettez dans redis ne seront pas supprimées, la seule exception est l'utilisation d'EXPIRE.


2
Alors, que fait-il quand il manque de mémoire? Il va simplement stocker de nouvelles données sur le disque et non dans la mémoire?
Cory

1
Ceci est (maintenant) incorrect, Redis a un mécanisme d'expulsion clé, avec plusieurs politiques disponibles: redis.io/topics/lru-cache
LoicAG

@LoicAG: Cela me semble parfaitement correct ... à moins qu'il n'y ait une politique d'expriation, Redis n'expulsera aucune clé. Et c'est bien: je ne peux pas, par exemple, me permettre de laisser Redis se débarrasser des clés tout seul.
Michael

@Cory: si une politique d'éviction est mise en place, elle supprimera les clés existantes. Cependant, si vous n'avez défini aucune stratégie d'éviction, vous devriez recevoir une erreur de mémoire insuffisante.
Michael

@Michael Je suppose que c'est une question de terminologie: il y a toujours une politique maxmemory en place, et la valeur par défaut est en effet "noeviction"; mais les politiques «allkeys-lru» et «allkeys-random» expulsent les clés de l'ensemble entier, et les autres («volatile- *») expulsent les clés du sous-ensemble de clés qui ont un TTL défini.
LoicAG
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.