当 Redis 耗尽内存时,它会做什么?

这个问题可能很简单,但我很难找到答案。Redis 2.0如何处理最大分配内存不足的问题?它如何决定要删除哪些数据,或者在内存中保留哪些数据?

72629 次浏览

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

我最近才开始读 Redis 的报道,所以我不是很确定。但是,我发现了一些可能有用的花边新闻。

以下是来自 http://antirez.com/post/redis-as-LRU-cache.html的片段:

将 Redis 用作缓存的另一种方法是 Maxmemory 指令,一个特性 允许指定最大值的 要使用的内存量。当新数据 被添加到服务器,并且内存 已经达到上限,服务器 将删除一些旧数据删除一个 易失性键,即具有 过期(超时)设置,即使 钥匙还远远没有过期 自然而然地。

此外,Redis 2.0有一个 VM 模式,其中所有键都必须放入内存中,但是很少使用的键的值可以放在磁盘上:

如果您打开了虚拟内存功能(编辑: 现已废弃) ,那么当内存耗尽时,Redis 将开始将“不常用”的数据存储到磁盘。

如果 Redis 中的虚拟内存被禁用(默认情况下)并且设置了 maxmemory参数(默认情况下) ,Redis 将不会使用超过 maxmemory允许的任何内存。如果关闭 maxmemory,Redis 将开始使用虚拟内存(即交换) ,性能将大幅下降。

当到达 maxmemory时,较新版本的 Redis 具有不同的策略:

  • 中删除一个密钥 有过期限的,试图 删除最近没有使用的键。
  • 中删除一个密钥 有过期限的,试图 以较短的剩余时间移除键 活下去。
  • 移除一个 在具有 过期。
  • allkeys-lru一样 volatile-lru,但将删除每个 类型的钥匙,都是普通的钥匙或钥匙 有一个过期限制。
  • allkeys-random- 像 volatile-random,但会删除 各种钥匙,都是普通钥匙 还有过期的钥匙。

如果您选择的策略只删除带有 EXPIRE 集的键,那么当 Redis 耗尽内存时,看起来程序只是中止了 malloc ()操作。也就是说,如果尝试存储更多数据,写操作就会失败。

更多信息的链接:

我最近经历了一个没有空闲内存的情况,我的应用程序陷入停顿(写不可能,读是可能的) ,运行 PHP 脚本中途停止,不得不手动 kill -9(甚至在内存可用之后)。

我假设数据丢失(或数据不一致)已经发生,所以我做了一个 flushdb并从备份中恢复。吸取教训了吗?后援是你的朋友。

来自 < strong > 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

如果你想知道当 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'.

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