Cosa fa Redis quando esaurisce la memoria?


111

Questa potrebbe essere una domanda facile, ma ho difficoltà a trovare la risposta. In che modo Redis 2.0 gestisce l'esaurimento della memoria massima allocata? Come decide quali dati rimuovere o quali dati conservare in memoria?


Risposte:


94

Se hai attivato la funzionalità di memoria virtuale (nuova nella versione 2.0 o 2.2, credo), Redis inizia a memorizzare i dati "non utilizzati di frequente" su disco quando la memoria si esaurisce.

Se la memoria virtuale in Redis è disabilitata, sembra che la memoria virtuale del sistema operativo inizi ad esaurirsi (ovvero lo scambio) e le prestazioni diminuiscano enormemente.

Ora puoi anche configurare Redis con un parametro maxmemory, che impedisce a Redis di utilizzare ulteriore memoria (impostazione predefinita).

Le versioni più recenti di Redis hanno vari criteri quando viene raggiunto maxmemory:

  • volatile-lru rimuove una chiave tra quelle con una scadenza impostata, cercando di rimuovere le chiavi non utilizzate di recente.
  • volatile-ttl rimuove una chiave tra quelle con una scadenza impostata, provando a rimuovere le chiavi con poco tempo rimanente da vivere.
  • volatile-casuale rimuove una chiave casuale tra quelle con una scadenza impostata.
  • allkeys-lru come volatile-lru, ma rimuoverà ogni tipo di chiave, sia chiavi normali che chiavi con una scadenza impostata.
  • allkeys-random come volatile-random, ma rimuoverà ogni tipo di chiave, sia chiavi normali che chiavi con una scadenza impostata.

Se scegli un criterio che rimuove solo le chiavi con un set EXPIRE, quando Redis esaurisce la memoria, sembra che il programma interrompa semplicemente l'operazione malloc (). Cioè, se provi a memorizzare più dati, l'operazione fallisce miseramente.

Alcuni link per maggiori informazioni (dal momento che non dovresti credermi sulla parola):


8
Redis Virtual Memory è ora deprecato. Vedi redis.io/topics/virtual-memory
cgaldiolo

19

Da redis.conf , versione 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
L'impostazione predefinita maxmemory-policyin Redis 3.2 è ora noeviction: raw.githubusercontent.com/antirez/redis/3.2/redis.conf
LoicAG

5

Aggiorna 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

Ho appena iniziato a leggere di Redis, quindi non sono positivo. Ma mi sono imbattuto in alcuni bocconcini che potrebbero essere utili.

Ecco uno snippet da http://antirez.com/post/redis-as-LRU-cache.html :

Un altro modo per utilizzare Redis come cache è la direttiva maxmemory, una funzionalità che consente di specificare una quantità massima di memoria da utilizzare. Quando vengono aggiunti nuovi dati al server e il limite di memoria è già stato raggiunto, il server rimuoverà alcuni vecchi dati eliminando una chiave volatile, cioè una chiave con uno EXPIRE (un timeout) impostato, anche se la chiave è ancora lontana dalla scadenza automatica.

Inoltre, Redis 2.0 ha una modalità VM in cui tutte le chiavi devono entrare in memoria, ma i valori per le chiavi usate raramente possono essere su disco:


2

Se ti chiedi cosa risponde effettivamente Redis (2.8) quando raggiunge il massimo definito dalla sua configurazione, assomiglia a questo:

$ 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

Di recente ho riscontrato una situazione di assenza di memoria libera e la mia applicazione si è bloccata (scrittura non possibile, letture possibili), l'esecuzione di script PHP si è interrotta a metà strada e ha dovuto essere eseguita kill -9manualmente (anche dopo che la memoria era reso disponibili).

Presumevo che si fosse verificata una perdita di dati (o incoerenza dei dati), quindi ho eseguito flushdbe ripristinato dai backup. Lezione imparata? I backup sono tuoi amici.


-3

Redis non è una cache come memcached, per impostazione predefinita (dove il maxmemory-policyparametro è impostato su noeviction) tutti i dati che inserisci in redis non verranno rimossi, l'unica eccezione è nell'uso di EXPIRE.


2
Quindi cosa fa quando si esaurisce la memoria? Memorizzerà solo i nuovi dati nel disco e non nella memoria?
Cory

1
Questo non è (ora) corretto, Redis ha un meccanismo di sfratto chiave, con diverse politiche disponibili: redis.io/topics/lru-cache
LoicAG

@LoicAG: Mi sembra perfettamente corretto ... a meno che non ci sia una politica di espiazione, Redis non sfratterà nessuna chiave. E questo è un bene: io, per esempio, non posso permettermi che Redis si sbarazzi delle chiavi da solo.
Michael

@Cory: se è stata impostata una politica di sfratto, rimuoverà le chiavi esistenti. Tuttavia, se non hai impostato alcun criterio di rimozione, dovresti ricevere un errore di memoria esaurita.
Michael

@Michael Suppongo sia una questione di terminologia: c'è sempre una politica di maxmemory in atto, e l'impostazione predefinita è davvero "noeviction"; ma le politiche "allkeys-lru" e "allkeys-random" rimuovono le chiavi dall'intero set, e le altre ("volatile- *") rimuovono le chiavi dal sottoinsieme di chiavi che hanno un TTL definito.
LoicAG
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.