上一讲提到,缓存的容量老是小于后端数据库的。随着业务系统的使用,缓存数据会撑满内存空间,该怎么处理呢?算法
本节咱们来学习内存淘汰机制。在Redis 4.0以前有6种内存淘汰策略,以后又增长2种,一共8种,以下图所示:数据库
对于TTL、Random比较好理解,下面学习一下LRU和LFU算法。后端
LRU算法,全称Least Recently Used。缓存
其中MRU端指最近访问的数据;LRU端指最先访问的数据。dom
被访问的数据和新插入的数据会移到MRU端,空间满了后从LRU端删除。这样一来,最先访问的数据会逐渐被淘汰。性能
但LRU算法也有其缺点:学习
而Redis对其进行简化:spa
当再次淘汰数据时,会挑选数据放到第一次淘汰时的候选集合,要求小于候选集合中最小的lru值才能加入。code
其中maxmemory-samples
配置项:表示选出的个数N。能够经过如下命令进行设置:server
CONFIG SET maxmemory-samples 100
LFU算法是在LRU策略基础上,为每一个数据增长一个计数器,来统计这个数据的访问次数。
使用LFU策略筛选淘汰数据时,根据数据的访问次数进行筛选,把访问次数最低的数据淘汰。若是两个数据访问次数相同,再比较两个数据的访问时效性,把更久的数据淘汰。
LFU也是使用RedisObject的lru字段来实现。
把24bit的lru字段拆分红两部分:
当LFU策略淘汰数据时,Redis在候选集合中,根据lru字段的后8bit选择访问次数最小的数据进行淘汰。若是访问次数相同,再根据lru字段的前16bit值大小,选择更久的数据进行淘汰。
Redis并无采用数据每被访问一次,就+1的规则,而是采用一个相似于随机+1的规则:
double r = (double)rand()/RAND_MAX; ... double p = 1.0/(baseval*server.lfu_log_factor+1); if (r < p) counter++;
经过设置 lfu_log_factor
配置项来控制计数器值增长的速度,避免counter很快到255。下图是 lfu_log_factor
设置不一样值时,counter的增加状况: