上一讲提到,缓存的容量总是小于后端数据库的。随着业务系统的使用,缓存数据会撑满内存空间,该怎么处理呢?
本节我们来学习内存淘汰机制。在Redis 4.0之前有6种内存淘汰策略,之后又增加2种,一共8种,如下图所示:
noeviction策略:内存空间达到maxmemory时,不会淘汰数据,有新写入时会返回错误。
volatile-ttl策略:针对设置了过期时间的键值对,根据过期时间的先后进行修改,越早过期的越先被删除。
volatile-random策略:在设置了过期时间的键值对中,进行随机删除。
volatile-lru策略:使用LRU算法筛选设置了过期时间的键值对,进行删除。
volatile-lfu策略:使用LFU算法筛选设置了过期时间的键值对,进行删除。
allkeys-random策略:在所有键值对中随机选择并删除数据。
allkeys-lru策略:使用LRU算法在所有数据中进行筛选并删除数据。
allkeys-lfu策略:使用LFU算法在所有数据中进行筛选并删除数据。
对于TTL、Random比较好理解,下面学习一下LRU和LFU算法。
LRU算法LRU算法,全称Least Recently Used。
其中MRU端指最近访问的数据;LRU端指最早访问的数据。
被访问的数据和新插入的数据会移到MRU端,空间满了后从LRU端删除。这样一来,最早访问的数据会逐渐被淘汰。
但LRU算法也有其缺点:
需要用链表管理所有缓存数据,带来额外的空间开销
大量数据被访问,就会带来很多链表移动操作,降低Redis性能
而Redis对其进行简化:
Redis会记录每个数据的最近一次访问的时间戳(RedisObject中的lru字段)
Redis第一次淘汰数据时,会随机选出N个数据,作为一个候选集合。
然后比较这N个数据的lru,把lru最小的从缓存中淘汰。
当再次淘汰数据时,会挑选数据放到第一次淘汰时的候选集合,要求小于候选集合中最小的lru值才能加入。
其中maxmemory-samples配置项:表示选出的个数N。可以通过以下命令进行设置:
CONFIG SET maxmemory-samples 100