一.为什么需要缓存淘汰机制
- Redis缓存使用内存来保存数据,避免业务应用从后端数据库中读取数据,可以提升应用响应速度。
- 为什么我们不把所有要访问的数据都放入到缓存中呢?性价比不高。
- MYSQL中有1TB数据,如果我们使用Redis把这1TB数据缓存起来,1TB内存价格是3.5w元但是1TB磁盘的价格只有800人民币左右。另一方面,数据访问大多数时候遵循二八原则,百分之八十的请求只访问百分之20的数据。
缓存空间容量必然要小于后端数据库的数据总量。
二.缓存数据的淘汰机制
数据淘汰机制包含两步:
- 根据一定策略筛选出对应用访问来说并不重要的数据;
- 将这些数据从缓存中删除,为新来的数据腾出空间;
三.设置多大的缓存容量合适
- "长尾效应" --蓝线: 二八原理。百分之20的数据贡献了百分之80的访问。
- "重尾效应"--红线:20% 的数据可能贡献不了 80% 的访问,而剩余的 80% 数据反而贡献了更多的访问量。
正因为20%的数据不一定贡献80%的访问量,我们不能简单的按照"总数量的20%来设置缓存最大空间容量"。需要结合数据实际访问特征和成本开销来综合考虑。
建议把缓存容量设置为总数据量的15%-30%,兼顾访问性能和内存空间开销。
四.Redis缓存有哪些淘汰策略?
- 不进行数据淘汰策略,只有noeviction。
- 设置了过期时间的数据淘汰策略: volatle-random,volatitle-ttl,volatitle-lru,volatitle-lfu。
- 所有数据范围内淘汰:allkeys-lru,allkeys-random, allkeys-lfu。
- 默认情况下,Redis在使用内存空间超过maxmemory时,并不会被淘汰,也就是设定的noeviction 策略。
- 一旦缓存被写满了,Redis不再提供服务,直接报错。
- Redis用作缓存时候,实际数据集通常会大于缓存容量的,总会有新的数据写入缓存,因此noeviction策略不符合Redis使用规则。
volatitle-random.volatitle-ttl,volatitle-lru和volatitle-lru这四种淘汰策略:
- 他们筛选的候选数据范围,被限制在已设置过期时间的键值对上。
- 即使缓存没有写满,这些数据过期也会被删除。
- volatitle-ttl在筛选时,会针对设置了过期时间的键值对,根据过期时间先后删除,越早过去的越先被删除。
- volatitle-random,在设置了过期时间的键值对中,随机删除。
- volatitle-lru会使用LRU算法帅选设置看过期时间的键值对。
- volatile-lfu 会使用 LFU 算法选择设置了过期时间的键值对。
allkeys-lru、allkeys-random、allkeys-lfu 这三种淘汰策略:
- allkeys-random 策略,从所有键值对中随机选择并删除数据
- allkeys-lru 策略,使用 LRU 算法在所有数据中进行筛选
- allkeys-lfu 策略,使用 LFU 算法在所有数据中进行筛选
如果一个键值对被删除 策略选中了,即使他的过期时间还没到,也需要被删除。当然,如果他的过期时间到了但未被选中,同样会被删除。
五.LRU 算法
Least Recently Used 最近最少使用原则来筛选数据,最不常用的数据会被筛选出来,最近频繁使用的数据会留在缓存中。
LRU算法实现
- LRU会把所有的数据组成一个链表,链表 的头和尾分别表示MRU端和LRU端 ,分别代表最近最常使用的数据和最近最不常的数据。
LRU算法思想:
- 刚刚被访问的数据肯定还会再次访问,所以我们把它放到MRU端;
- 长久不访问的数据,肯定不会再被访问了,所以我们就让它后移到 LRU 端,并有限删除它。
Redis的LRU算法:
- LRU算法被做简化,以减轻数据 淘汰对缓存性能;
- Redis 默认会记录每个数据的最近一次访问的时间戳(由键值对数据结构 RedisObject 中的 lru 字段记录)。
- Redis在决定淘汰数据的时,第一次会随机选出N个数据,把他们作为一个候选集合。
- Redis会比较这N个数据的lru字段,把lru字段值中最小的数据从缓存中淘汰出去。
- Redis提供了一个配置参数maxmemory-samples,这个参数就是Redis选出数据个数N。
- 我们执行这个命令,可以让Redis选出100个数据作为候选数据集。
- 能进入候选集合的数据lru字段值必须小于候选集合中最小的lru值。
- 当有新的数据进入候选数据集的时候,如果候选数据集中的数据个数达到了maxmemory-samples,Redis 就把候选数据集中 lru 字段值最小的数据淘汰出去。
Redis 缓存不用为所有的数据维护一个大链表,也不用在每次数据访问时都移动链表项,提升了缓存的性能。
六.三个使用建议
- 优先使用allkeys-lru策略。这样可以充分利用LRU这一经典缓存算法优势,将最近最长访问的数据留在缓存中,提升应用的访问性能。适用于业务数据中有明显的冷热数据区分。
- 如果业务应用中的数据访问频率相差不大,没有明显的冷热数据区分,建议使用allkeys-random策略,随机选择淘汰的数据就行。
- 如果业务有置顶需求,比如置顶新闻,置顶视频,使用volatitle-lru策略,同时不给置顶数据设置过期时间。置顶数据一直不会被 删除,其他数据会在过期时候根据LRU规则进行筛选。