Esta pode ser uma pergunta fácil, mas estou tendo dificuldade em encontrar a resposta. Como o Redis 2.0 lida com o esgotamento da memória máxima alocada? Como ele decide quais dados remover ou quais dados manter na memória?
Se você tiver a funcionalidade de memória virtual ativada (nova na versão 2.0 ou 2.2, eu acho), o Redis começará a armazenar os dados "usados com menos frequência" em disco quando a memória acabar.
Se a memória virtual no Redis estiver desabilitada, parece que a memória virtual do sistema operacional começa a se esgotar (ou seja, troca) e o desempenho cai tremendamente.
Agora, você também pode configurar o Redis com um parâmetro maxmemory, que evita que o Redis use mais memória (o padrão).
As versões mais recentes do Redis têm várias políticas quando maxmemory é atingido:
volatile-lru remove uma chave entre aquelas com um conjunto de expiração, tentando remover chaves não usadas recentemente.
volatile-ttl remove uma chave entre aquelas com um conjunto de expiração, tentando remover chaves com pouco tempo restante de vida.
volatile-random remove uma chave aleatória entre aquelas com um conjunto de expiração.
allkeys-lru como volatile-lru, mas irá remover todo tipo de chave, tanto as chaves normais quanto as chaves com um conjunto de expiração.
allkeys-random como volatile-random, mas removerá todos os tipos de chaves, tanto as chaves normais quanto as chaves com um conjunto de expiração.
Se você escolher uma política que remove apenas chaves com um EXPIRE definido, quando o Redis ficar sem memória, parece que o programa apenas aborta a operação malloc (). Ou seja, se você tentar armazenar mais dados, a operação falhará terrivelmente.
Alguns links para mais informações (já que você não deve acreditar apenas na minha palavra):
# 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
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
Outra forma de usar o Redis como cache é a diretiva maxmemory, um recurso que permite especificar a quantidade máxima de memória a ser usada. Quando novos dados são adicionados ao servidor, e o limite de memória já foi atingido, o servidor irá remover alguns dados antigos excluindo uma chave volátil, ou seja, uma chave com EXPIRE (um tempo limite) definido, mesmo que a chave ainda esteja longe de expirar automaticamente.
Além disso, o Redis 2.0 tem um modo VM em que todas as chaves devem caber na memória, mas os valores das chaves raramente usadas podem estar no disco:
Se você está se perguntando o que o Redis (2.8) realmente responde quando atinge o máximo definido por sua configuração, é assim:
$ 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'.
Recentemente, experimentei uma situação de falta de memória livre e meu aplicativo parou (gravações não são possíveis, leituras são possíveis), a execução de scripts PHP parou no meio do caminho e teve que ser feito kill -9manualmente (mesmo depois que a memória foi disponibilizado).
Presumi que tivesse ocorrido perda de dados (ou inconsistência de dados), então fiz um flushdbe restaurei os backups. Lição aprendida? Os backups são seus amigos.
O Redis não é um cache como o memcached, por padrão (onde o maxmemory-policyparâmetro é definido como noeviction) todos os dados que você coloca no redis não serão removidos, a única exceção é o uso de EXPIRE.
Então, o que ele faz quando fica sem memória? Ele apenas armazenará novos dados no disco e não na memória?
Cory
1
Isso (agora) está incorreto, o Redis tem um mecanismo de despejo chave, com várias políticas disponíveis: redis.io/topics/lru-cache
LoicAG
@LoicAG: Parece perfeitamente correto para mim ... a menos que haja uma política de expreciação, o Redis não removerá nenhuma chave. E isso é bom: eu, por exemplo, não posso permitir que o Redis se livre das chaves sozinho.
Michael,
@Cory: Se houver uma política de despejo definida, ela removerá as chaves existentes. No entanto, se você não definiu nenhuma política de despejo, deverá receber um erro de falta de memória.
Michael,
@Michael Suponho que seja uma questão de terminologia: há sempre uma política de maxmemory em vigor, e o padrão é de fato "noeviction"; mas as políticas "allkeys-lru" e "allkeys-random" expulsam chaves de todo o conjunto e as outras ("volatile- *") expulsam chaves do subconjunto de chaves que têm um TTL definido.
Respostas:
Se você tiver a funcionalidade de memória virtual ativada (nova na versão 2.0 ou 2.2, eu acho), o Redis começará a armazenar os dados "usados com menos frequência" em disco quando a memória acabar.
Se a memória virtual no Redis estiver desabilitada, parece que a memória virtual do sistema operacional começa a se esgotar (ou seja, troca) e o desempenho cai tremendamente.
Agora, você também pode configurar o Redis com um parâmetro maxmemory, que evita que o Redis use mais memória (o padrão).
As versões mais recentes do Redis têm várias políticas quando maxmemory é atingido:
Se você escolher uma política que remove apenas chaves com um EXPIRE definido, quando o Redis ficar sem memória, parece que o programa apenas aborta a operação malloc (). Ou seja, se você tentar armazenar mais dados, a operação falhará terrivelmente.
Alguns links para mais informações (já que você não deve acreditar apenas na minha palavra):
fonte
De redis.conf , versão 2.8
fonte
maxmemory-policy
no Redis 3.2 agora énoeviction
: raw.githubusercontent.com/antirez/redis/3.2/redis.confAtualizar redis 4.0
fonte
Recentemente comecei a ler sobre o Redis, então não tenho certeza. Mas, encontrei alguns boatos que podem ser úteis.
Aqui está um snippet de http://antirez.com/post/redis-as-LRU-cache.html :
Além disso, o Redis 2.0 tem um modo VM em que todas as chaves devem caber na memória, mas os valores das chaves raramente usadas podem estar no disco:
fonte
Se você está se perguntando o que o Redis (2.8) realmente responde quando atinge o máximo definido por sua configuração, é assim:
fonte
Recentemente, experimentei uma situação de falta de memória livre e meu aplicativo parou (gravações não são possíveis, leituras são possíveis), a execução de scripts PHP parou no meio do caminho e teve que ser feito
kill -9
manualmente (mesmo depois que a memória foi disponibilizado).Presumi que tivesse ocorrido perda de dados (ou inconsistência de dados), então fiz um
flushdb
e restaurei os backups. Lição aprendida? Os backups são seus amigos.fonte
O Redis não é um cache como o memcached, por padrão (onde o
maxmemory-policy
parâmetro é definido comonoeviction
) todos os dados que você coloca no redis não serão removidos, a única exceção é o uso de EXPIRE.fonte