Redis内存不足时会做什么?


Answers:


94

如果您打开了虚拟内存功能(我认为是2.0或2.2中的新增功能),那么当内存用尽时,Redis将开始将“不太常用”的数据存储到磁盘上。

如果禁用Redis中的虚拟内存,则好像操作系统的虚拟内存开始用尽(即交换),并且性能会大大下降。

现在,您还可以使用maxmemory参数配置Redis,这可以防止Redis使用更多的内存(默认值)。

达到maxmemory时,较新版本的Redis具有各种策略:

  • volatile-lru删除具有过期集的密钥中的一个,以尝试删除最近未使用的密钥。
  • volatile-ttl删除具有过期集的密钥,并尝试删除剩余生存时间短的密钥。
  • volatile-random从具有到期集的密钥中删除一个随机密钥。
  • allkeys-lru与volatile-lru类似,但是将删除每种密钥,包括普通密钥或具有过期集的密钥。
  • allkeys-random和volatile-random一样,但是将删除各种键,包括普通键和具有过期集的键。

如果选择仅删除设置了EXPIRE的键的策略,则当Redis内存不足时,程序似乎只是中止malloc()操作。也就是说,如果您尝试存储更多数据,则操作只会惨败。

一些链接以获取更多信息(因为您不应该相信我的话):


8
Redis虚拟内存现已弃用。参见redis.io/topics/virtual-memory
cgaldiolo16年

19

redis.conf版本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
maxmemory-policy现在Redis 3.2中的默认值是noevictionraw.githubusercontent.com/antirez/redis/3.2/redis.conf
LoicAG 2016年

5

更新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

我刚刚开始阅读有关Redis的文章,所以我并不乐观。但是,我确实遇到了一些有用的窍门。

这是来自http://antirez.com/post/redis-as-LRU-cache.html的摘录:

将Redis用作缓存的另一种方法是maxmemory指令,该功能允许指定要使用的最大内存量。当将新数据添加到服务器并且已经达到内存限制时,服务器将删除一些旧数据,从而删除易失性密钥,即设置了EXPIRE(超时)的密钥,即使该密钥仍然很远自动过期。

另外,Redis 2.0具有VM模式,其中所有密钥都必须适合内存,但是很少使用的密钥的值可以在磁盘上:


2

如果您想知道Redis(2.8)在达到其配置所定义的最大值时实际上会做出什么响应,则如下所示:

$ 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

最近,我遇到了一个无内存的情况,我的应用程序停顿了(无法写,无法读),运行PHP脚本在途中停滞不前,不得不kill -9手动进行操作(即使在内存耗尽后也是如此)。可用)。

我以为发生了数据丢失(或数据不一致),所以我做了一次flushdb并从备份中恢复了。学过的知识?备份是您的朋友。


-3

Redis不是像memcached一样的缓存,默认情况下(maxmemory-policy参数设置为noeviction),不会删除您放入redis的所有数据,唯一的例外是使用EXPIRE。


2
那么,当内存不足时该怎么办?它将仅将新数据存储在磁盘中而不是内存中吗?
Cory

1
(现在)这是不正确的,Redis具有一个关键的驱逐机制,其中包含几种可用策略:redis.io/topics/lru-cache
LoicAG 2015年

@LoicAG:听起来对我来说完全正确……除非有一项限制政策,否则Redis不会驱逐任何钥匙。很好:例如,我无法让Redis自己摆脱密钥。
Michael

@Cory:如果设置了逐出策略,它将删除现有密钥。但是,如果您未设置任何驱逐策略,则应收到内存不足错误。
迈克尔

@Michael我想这是一个术语问题:总有一个maxmemory策略,默认值确实是“ noeviction”;但是“ allkeys-lru”和“ allkeys-random”策略从整个集合中逐出密钥,而其他(“ volatile- *”)则从已定义TTL的密钥子集中逐出密钥。
LoicAG '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.