Risposte:
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:
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):
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
maxmemory-policy
in Redis 3.2 è ora noeviction
: raw.githubusercontent.com/antirez/redis/3.2/redis.conf
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
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:
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'.
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 -9
manualmente (anche dopo che la memoria era reso disponibili).
Presumevo che si fosse verificata una perdita di dati (o incoerenza dei dati), quindi ho eseguito flushdb
e ripristinato dai backup. Lezione imparata? I backup sono tuoi amici.
Redis non è una cache come memcached, per impostazione predefinita (dove il maxmemory-policy
parametro è impostato su noeviction
) tutti i dati che inserisci in redis non verranno rimossi, l'unica eccezione è nell'uso di EXPIRE.