【Redis】内存淘汰策略
文章目录
- 什么是内存淘汰策略
- 设置`Redis`最大内存
- 执行内存淘汰策略的流程
- `Redis`的八大内存淘汰策略
- 深入源码进行理解
- 内存淘汰策略流程
什么是内存淘汰策略
Redis
内存淘汰策略是指当Redis
的内存使用达到其配置的最大内存限制(maxmemory
)时,Redis
根据预设的策略自动删除一部分键(key
)及其对应的值(value
),以释放内存空间,从而避免内存溢出(OOM
,Out Of Memory
)错误的发生。Redis
提供了多种内存淘汰策略,以满足不同应用场景的需求。
设置Redis
最大内存
在Linux
系统中,使用命令:vim /etc/redis/redis.conf
,打开Redis
的配置文件.
如:maxmemory 1gb
执行内存淘汰策略的流程
- 进行内存淘汰的时机: 在
Redis
处理客户端命令之前,都会检查一遍内存,然后尝试淘汰内存
在前面的学习过程中,我们了解到,在执行Redis
命令时,会调用processCommand
来进行Redis
命令的执行.
分析该源码的内容:
在执行Redis
命令之前,都会调用processCommand
函数,在设定了server.maxmemory
属性并且未有执行Lua
脚本的情况下,尝试淘汰内存,调用performEvictions()
函数,尝试淘汰内存,如果内存淘汰失败,拒绝执行该Redis
命令.(因为Redis
中默认的内存淘汰策略是noeviction
,不进行key
的删除,而是直接不允许写入新的数据)
Redis
的八大内存淘汰策略
在配置文件中可以对不同的内存淘汰策略进行选择:
打开/etc/redis/redis.conf
,Redis
的配置文件,找到maxmemory-policy
属性.
Redis
支持八种不同的策略来选择要删除的key
:
noeviction
:不淘汰任何key
,但是内存满时不允许写入新的数据,这是Redis
默认的内存淘汰策略volatile-ttl
:对设置了ttl
的key
,比较key
的剩余ttl
的值,ttl
越小越先被淘汰.allkeys-random
: - 对全体的key
进行随机淘汰,也就是从db->dict
(对所有的key
)中随机挑选Volatile-random
:对设置了ttl
的key
,随机进行淘汰.也就是从db->expires
(对所有带过期时间的key
)中随机挑选Allkeys-lru
:对全体的key
,基于lru
算法进行淘汰Volatile-lru
:对于设置了ttl
的key
,基于lru
算法进行淘汰Allkeys-lru
:对于全体key
,基于lfu
算法进行淘汰volatile-lfu
:对于设置了ttl
的key
,基于lfu
进行淘汰
LRU
:最少最近使用,用当前的时间减去最后一次访问的时间(即该key
多久没有被访问),这个值越大则淘汰的优先级越高.LFU
:最少频率使用,会统计每个key
的访问概率,值越小淘汰级别越高.
总结八大淘汰策略:
- 淘汰范围
- 全体
key
- 全体设置了
ttl
的key
- 淘汰算法
TTL
排序LRU
排序LFU
排序
深入源码进行理解
redis
如何统计key
的最近的使用时间和访问频率呢?
Redis
的数据都会被封装为RedisObject
结构中:
LFU
的访问次数之所以叫做逻辑访问次数,是因为并不是每次key
被访问都计数,而是通过运算:
- 生成
0~1
之间的随机数R
- 计算
1
/(旧次数*lfu_log_factor+1
),记录为P
,lfu_log_factor
默认为10
- 如果
R<P
,则计数器+1
,且最大不超过255
- 访问次数会随着时间衰减,距离上一次访问时间间隔
lfu_decay_time
分钟(默认1
),计数器-1
(比如某个key
已经255
分钟没有被访问了,就会减少到0
,所以LFU
的前16
位需要记录最近一次访问的时间,单位是分钟)
内存淘汰策略流程
这里我们重点理解
eviction_pool
- 这里相当于一个淘汰池,因为如果我们每次进行内存淘汰时,都将所有的
key
进行精确的排序,所消耗的时间是相当大的,所以这里进行了一个相对精确的筛选,也就是从每个DB
中随机选取maxmemory_samples
个数据进入淘汰池中,再按照选择的淘汰算法(TTL
,LRU
,LFU
)进行排序.- 这里我们注意到此处的
idleTime
的计算方式:
TTL
算法:maxTTL
-TTL
LRU
算法 :now
-LRU
LFU
算法:255
-LFU
为什么要进行这样的计算,而不是直接使用数据呢?原因在于:在淘汰池中,我们进行的是升序排列,倒序淘汰的方式进行key
的淘汰.(maxTTL
-TTL
)进行升序排列,相当于TTL
进行降序排列;同理now-LRU
和255-LFU
的计算方式也是如此.