Redis通常用作缓存,以加快对较慢服务器或数据库的读取访问。由于缓存条目是持久存储的数据的副本,因此当该高速缓存耗尽内存时,通常可以安全地将它们逐出(如果需要,将来可以再次缓存它们)。
Redis允许你指定驱逐策略,当该高速缓存的大小超过设定的内存限制时,自动驱逐键。每当客户端运行一个新的命令向该高速缓存添加更多数据时,Redis会检查内存使用情况。如果它大于限制,Redis会根据选择的回收策略回收键,直到使用的总内存回到限制以下。
请注意,当一个命令向该高速缓存添加大量数据时(例如,将一个大的集合交集存储到一个新的键中),这可能会暂时超过限制的大量数据。
以下各节说明了如何配置该高速缓存的内存限制,还介绍了可用的回收策略以及何时使用这些策略。
maxmemory 配置项:内存管理的关键设置
`maxmemory` 配置项是 Redis 中用于控制数据集内存使用量的重要参数。它允许用户设定 Redis 实例可以使用的最大内存量,从而有效管理内存资源,防止 Redis 占用过多内存导致系统性能下降或崩溃。
配置方法
用户可以通过以下两种方式设置 `maxmemory` 配置项:
1. 通过 `redis.conf` 文件配置:
- 打开 Redis 配置文件 `redis.conf`。
- 找到 `maxmemory` 配置项,修改其值为所需的内存大小。例如,设置最大内存为 100 MB:
maxmemory 100mb
2. 通过 `CONFIG SET` 命令动态配置:
- 在 Redis 客户端中,使用 `CONFIG SET` 命令直接设置 `maxmemory`。例如,设置最大内存为 100 MB:
CONFIG SET maxmemory 100mb
配置示例
假设我们需要将 Redis 的最大内存设置为 100 MB,可以在 `redis.conf` 文件中进行如下配置:
maxmemory 100mb
或者通过 `CONFIG SET` 命令动态设置:
CONFIG SET maxmemory 100mb
配置说明
- 默认值:
- 在 64 位系统上,`maxmemory` 的默认值为 0,表示没有内存使用限制。
- 在 32 位系统上,`maxmemory` 的默认值为 3GB,这是 32 位系统地址空间的限制。
- 内存限制为零:
- 如果将 `maxmemory` 设置为 0,Redis 将不会对内存使用量进行任何限制。这在某些测试环境中可能有用,但在生产环境中应谨慎使用,以避免内存耗尽导致系统问题。
maxmemory
如果您使用了 复制 或持久化 功能,Redis将使用一些RAM作为缓冲区来存储等待的更新集写入副本或AOF文件。 此缓冲区使用的内存不不会计入maxmemory的设置限制内
。
这是因为键的驱逐操作本身会产生更新数据,而这些更新数据必须被添加到缓冲区中。如果这些更新数据被计入已使用的内存,那么在某些情况下,通过驱逐键节省的内存会被立即用于缓冲区中的更新数据。这反过来又会触发更多的驱逐操作,由此产生的反馈循环可能会不必要地将许多项目从缓存中驱逐出去。
如果您正在使用复制或持久化功能,我们建议您设置 `maxmemory`,以便留出一些 RAM 来存储缓冲区。请注意,对于 `noeviction` 策略,这并不是必要的(有关驱逐策略的更多信息,请参见下面的部分)。
内存达到限制时键驱逐策略
当 Redis 的内存使用量达到 `maxmemory` 设置的限制时,Redis 会根据配置的 `maxmemory-policy` 参数决定如何处理。常见的策略包括:
• noeviction:默认策略,当达到内存使用限制且客户端尝试执行可能会使用更多内存的命令时返回错误。
• volatile-lru:删除设置了过期时间且最近最少使用的键(LRU淘汰算法)。
• allkeys-lru:删除所有最近最少使用的键(LRU淘汰算法)。
• volatile-lfu:删除设置了过期时间且最不经常使用的键(LFU淘汰算法)。
• allkeys-lfu:删除所有最不经常使用的键(LFU淘汰算法)。
• volatile-random:随机淘汰设置了过期时间的键。
• allkeys-random:随机淘汰所有键。
• volatile-ttl:根据过期时间淘汰设置了过期时间的键,越早过期越早淘汰。
通过合理配置 `maxmemory` 和 `maxmemory-policy`,可以有效管理 Redis 的内存使用,确保系统在高负载和大数据量的情况下仍能稳定运行。
作为一些经验法则,如下:
`volatile-lru` 和 `volatile-random` 策略主要适用于您希望使用单个 Redis 实例来同时进行缓存以及存储一组持久化键的场景。然而,如果条件允许,您应考虑在这种情况下运行两个独立的 Redis 实例。
请注意,为键设置过期时间会消耗内存,因此像 `allkeys-lru` 这样的策略更加节省内存,因为它无需依赖过期时间即可执行操作。
LRU算法
LRU(Least Recently Used,最近最少使用)算法是根据数据在一段时间内是否被使用的记录来淘汰数据,该算法的核心思想是如果数据最近被使用,那么将来被使用的概率更高。可以把LRU算法理解为一个链表,会将新数据放在链表头部,在一段时间内,只要数据被使用就移到链表头部,链表满的时候就从链表尾部移出数据,即链表尾部的数据被淘汰。Redis中使用的算法近似于LRU算法,比如修改配置文件maxmemory–samples=5,表示在Redis中随机采样5个键,然后从中淘汰最少使用的键,因此采样键的数量与Redis库中键的数量越接近,淘汰的规则就越接近LRU算法。官方默认使用5个键,最多不超过10个键,越大就越消耗CPU的资源。采用LRU算法,如果一个热点数据在内存在LRU算法约定的时间段内没有被使用,非热点数据在这个时间段内反而被使用了,就可能误把热点数据淘汰了而留下非热点数据,因此在Redis 4版本后新增了LFU算法来解决这类问题。
LFU算法
LFU(Least Frequently Used,最近不常使用)算法根据数据使用的次数来淘汰数据,该算法的核心思想是如果数据过去被使用多次,那么将来被使用的频率更高。LFU算法反映了一个键的热度,不会像LRU算法中那样偶尔一次被使用就被误认为是热点数据。同样可以把LFU算法理解为一个链表,新数据放在链表尾部,链表中的数据按照被使用的次数降序排列,被使用次数相同的数据按最近使用的时间降序排列,链表满的时候从链表尾部移出数据。这样就避免了LRU算法可能存在的问题。需要注意的是LFU算法中数据使用的时间和使用次数(counter)。counter的衰减和两个配置有关。如果一个键长时间没有被使用,counter就会按衰减因子的值来减少,在衰减因子为1的情况下,N分钟没有访问,就要减N。
数据过期删除策略
当内存没占满时,在Redis中过期的键是通过惰性删除和定期删除来进行优化的。•
惰性删除:当键被访问时检查该键的过期时间,如果过期就删除此键。未过期但是没有被访问的键仍存放在内存中,自然就继续占用内存资源。
定期删除:每隔一段时间,随机检查设置了过期的键并删除已过期的键。Redis每10秒进行一次过期扫描。第一步,随机取20个设置了过期策略的键。第二步,检查这20个键,删除其中已过期的键。第三步,如果有超过25%的键已过期则重复第一步。
主从架构和数据持久化对数据的过期处理
在RDB持久化模式中,采用全量持久化,所以在持久化的时候会过滤掉已经过期的键。在AOF持久化模式中,当出现键过期时就会给AOF文件发送删除命令。需要注意的是,在主从架构中,从节点从来不会主动删除过期的数据。为了保证数据一致性,主节点会发送删除命令给从节点来处理已经过期的键。
翻译自:https://redis.io/docs/latest/develop/reference/eviction