Redis内存回收策略

Redis可能因内存不足出错或回收过久致系统停顿,了解其回收策略很重要。当内存达最大值,可配置淘汰键值。介绍了如volatile - lru、allkeys - lru等多种策略,还提及默认策略、算法特性、参数影响及回收策略的优缺点。

Redis会因为内存不足而产生错误,也会因为回收过久而导致系统长期的停顿,因此了解掌握Redis的回收策略十分重要。当Redis的内存达到规定的最大值时,可以进行配置进行淘汰键值,并且将一些键值对进行回收。

我们打开Redis安装目录下的redis.conf文件。配置文件中有这么一段话

# 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
  • volatile-lru:采用最近使用最少的淘汰策略,Redis将回收那些超时的(仅仅是超时的)键值对,也就是它只淘汰那些超时的键值对。

  • allkeys-lru:采用最近最少使用的淘汰策略,Redis将对所有(不仅仅是超时的)的键值对采用最近最少使用的淘汰策略。

  • volatile-lfu:采用最近最不常用的淘汰策略,所谓最近最不常用,也就是一定时期内被访问次数最少的。Redis将回收超时的键值对。

  • allkeys-lfu:采用最近最不常用的淘汰策略,Redis将对所有的键值对采用最近最不常用的淘汰策略。

  • volatile-random:采用随机淘汰策略删除超时的键值对。

  • allkeys-random:采用随机淘汰策略删除所有的键值对,这个策略不常用。

  • volatile-ttl:采用删除存活时间最短的键值对策略。

  • noeviction:不淘汰任何键值对,当内存满时,如果进行读操作,例如get命令,它将正常工作,而做写操作,它将返回错误,也就是说,当Redis采用这个策略内存达到最大的时候,它就只能读不能写了。

Redis默认采用noeviction策略。

LRU算法或者TTL算法都是不精确的算法,而是一个近似算法。

Redis不会通过对全部的键值对进行比较来确定最精确的时间值,因为这太消耗时间,导致回收垃圾占用的时间太多造成服务器卡顿。在配置文件中,有一个参数maxmemory-samples,它的默认值是5,如果采用volatile-ttl算法,我们可以看看下面这个过程,假设有7个即将超时的键值对

键值对剩余超时秒数备注
A16属于探测样本
A23属于探测样本
A34属于探测样本
A45属于探测样本
A52属于弹出样本中的最小值,因此最先删除
A61虽然是最短值,但不属于探测样本,因此没有被删除

当设置maxmemory-samples越大,则Redis删除的就越精确,但消耗CPU。

回收超时策略的缺点是必须指明超时的键值对,这会给程序开发带来一些设置超时的代码,增加刘开发者的工作量。对所有的键值对进行回收,有可能把正在使用的键值对删掉,增加了存储的不稳定性。对于垃圾回收的策略,还需要控制回收的时间。

### Redis 内存淘汰策略机制及实现 Redis内存管理机制是其性能优化的核心之一,当 Redis内存使用量达到配置的限制时(由 `maxmemory` 参数控制),Redis 会根据指定的内存淘汰策略来释放空间,以保证服务的可用性[^1]。以下是 Redis 内存淘汰策略的工作原理和实现细节。 #### 一、内存淘汰策略概述 Redis 提供了多种内存淘汰策略,这些策略通过 `maxmemory-policy` 配置项进行设置。根据键的范围和淘汰算法的不同,可以将这些策略分为三类[^5]: - **noeviction**:不淘汰任何键,当内存不足时直接返回错误。 - **allkeys**:在所有键中选择淘汰目标。 - **volatile**:仅在设置了过期时间的键中选择淘汰目标。 具体淘汰算法包括以下四种: 1. **随机淘汰(Random)**:随机选择键进行淘汰。 2. **最少使用(LRU, Least Recently Used)**:淘汰最久未使用的键。 3. **最少访问频率(LFU, Least Frequently Used)**:淘汰访问频率最低的键。 4. **基于大小(TTL, Time To Live)**:优先淘汰剩余存活时间较短的键。 #### 二、内存淘汰策略的实现细节 1. **随机淘汰** - 在 `allkeys-random` 和 `volatile-random` 策略中,Redis 使用伪随机数生成器从候选键集合中随机选择键进行淘汰[^5]。 - 这种方法简单高效,但可能会导致重要数据被意外删除。 2. **LRU 淘汰** - LRU 淘汰策略(如 `allkeys-lru` 和 `volatile-lru`)依赖于 Redis 的内部 LRU 数据结构,该结构记录每个键的最后访问时间[^1]。 - 当需要淘汰键时,Redis 会扫描一定数量的候选键,并选择最后访问时间最早的键进行淘汰。 - Redis 并不维护一个完整的全局 LRU 列表,而是通过采样技术(例如每轮检查 5 个随机键)来近似实现 LRU 淘汰[^2]。 3. **LFU 淘汰** - LFU 淘汰策略(如 `allkeys-lfu` 和 `volatile-lfu`)基于键的访问频率进行淘汰[^3]。 - Redis 使用一个计数器记录每个键的访问频率,淘汰时选择访问频率最低的键。 - 访问频率的计算结合了时间衰减因子,确保长期未访问的键也能被淘汰。 4. **TTL 淘汰** - TTL 淘汰策略(如 `volatile-ttl`)优先淘汰剩余存活时间较短的键[^4]。 - 这种策略特别适用于缓存场景,能够有效减少内存占用。 #### 三、内存淘汰策略的监控与优化 为了确保内存淘汰策略的有效性,建议通过监控工具(如 RedisInsight 或 Prometheus)实时跟踪内存使用情况和淘汰指标[^2]。常见的优化实践包括: - 根据业务需求选择合适的淘汰策略。 - 定期分析淘汰日志,识别高频淘汰的键并优化存储逻辑。 - 调整 `maxmemory` 配置以平衡内存使用和性能需求。 ```python # 示例:设置 maxmemory 和淘汰策略 redis-cli config set maxmemory 1gb redis-cli config set maxmemory-policy allkeys-lru ``` #### 四、内存回收机制 除了内存淘汰策略外,Redis 还通过定期删除和惰性删除两种方式来清除过期的键[^3]: - **惰性删除**:仅在访问某个键时检查其是否已过期,若已过期则立即删除。 - **定期删除**:后台线程定期扫描一定比例的过期键并删除。 这两种机制共同作用,确保过期键不会长时间占用内存。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值