Redis-内存回收
1 内存回收
Reids 所有的数据都是存储在内存中的,在某些情况下需要对占用的内存空间进行回收。内存回收主要分为两类,一类是 key 过期,一类是内存使用达到上限(max_memory)
触发内存淘汰。
1.1 过期策略
要实现 key 过期,我们有几种思路。
1.1.1 定时过期(主动淘汰)
每个设置过期时间的 key 都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的 CPU 资源去处理过期的
数据,从而影响缓存的响应时间和吞吐量。
1.1.2 惰性过期(被动淘汰)
只有当访问一个 key 时,才会判断该 key 是否已过期,过期则清除。该策略可以最大化地节省 CPU 资源,却对内存非常不友好。极端情况可能出现大量的过期 key 没有再
次被访问,从而不会被清除,占用大量内存。
1.1.3 定期过期
每隔一定的时间,会扫描一定数量的数据库的 expires 字典中一定数量的 key,并清除其中已过期的 key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不
同情况下使得 CPU 和内存资源达到最优的平衡效果。
Redis 中同时使用了惰性过期和定期过期两种过期策略。
问题:如果都不过期,Redis 内存满了怎么办?
1.2 淘汰策略
Redis 的内存淘汰策略,是指当内存使用达到最大内存极限时,需要使用淘汰算法来决定清理掉哪些数据,以保证新数据的存入。
1.2.1 最大内存设置
redis.conf 参数配置:
# maxmemory <bytes>
如果不设置 maxmemory 或者设置为 0,64 位系统不限制内存,32 位系统最多使用 3GB 内存。
动态修改:
redis> config set maxmemory 2GB
到达最大内存以后怎么办?
1.2.2 淘汰策略
不同于之前的版本,redis5.0为我们提供了八个不同的内存置换策略。很早之前提供了6种。
(1)volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
(2)volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
(3)volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
(4)volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
(5)allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。
(6)allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
(7)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
(8) no-enviction(驱逐):禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失。
这八种大体上可以分为4中,lru、lfu、random、ttl。
如果没有符合前提条件的 key 被淘汰,那么 volatile-lru、volatile-random 、volatile-ttl 相当于 noeviction(不做内存回收)。
动态修改淘汰策略:
redis> config set maxmemory-policy volatile-lru
建议使用 volatile-lru,在保证正常服务的情况下,优先删除最近最少使用的 key。