通常来讲,缓存的容量是小于数据总量的,因此,当缓存数据愈来愈多,Redis 不可避免的会被写满,这时候就涉及到 Redis 的内存淘汰机制了。咱们须要选定某种策略将“不重要”的数据从 Redis 中清除,为新的数据腾出空间。redis
咱们应该为 Redis 设置多大的内存容量呢?算法
根据“八二原理“,即 80% 的请求访问了 20% 的数据,所以若是按照这个原理来配置,将 Redis 内存大小设置为数据总量的 20%,就有可能拦截到 80% 的请求。固然,只是有可能,对于不一样的业务场景须要进行不一样的配置,通常建议把缓存容量设置为总数据量的 15% 到 30%,兼顾访问性能和内存空间开销。shell
配置方式(以 5GB 为例,若是不带单位则默认单位是字节):缓存
命令行数据结构
config set maxmemory 5gb
配置文件dom
查看 maxmemory 命令性能
config get maxmemory
在 Redis 4.0 版本以前有 6 种策略,4.0 增长了 2种,主要新增了 LFU 算法。命令行
下图为 Redis 6.2.0 版本的配置文件:code
其中,默认的淘汰策略是 noevition,也就是不淘汰内存
咱们能够对 8 种淘汰策略能够分为两大类:
不进行淘汰的策略
noevition,此策略不会对缓存的数据进行淘汰,当内存不够了就会报错,所以,若是真实数据集大小大于缓存容量,就不要使用此策略了。
会进行淘汰的策略
以 volatile 开头的策略只针对设置了过时时间的数据,即便缓存没有被写满,若是数据过时也会被删除。
以 allkeys 开头的策略是针对全部数据的,若是数据被选中了,即便过时时间没到,也会被删除。固然,若是它的过时时间到了但未被策略选中,一样会被删除。
那么咱们如何配置过时策略呢?
命令行
config set maxmemory-policy allkeys-lru
配置文件
首先简单介绍一下 LRU 算法:
LRU 全称是 Least Recently Used,即最近最少使用,会将最不经常使用的数据筛选出来,保留最近频繁使用的数据。
LRU 会把全部数据组成一个链表,链表头部称为 MRU,表明最近最常使用的数据;尾部称为 LRU表明最近最不常使用的数据;
下图是一个简单的例子:
可是,若是直接在 Redis 中使用 LRU 算法也会有一些问题:
LRU 算法在实现过程当中使用链表管理全部缓存的数据,这会给 Redis 带来额外的开销,并且,当有数据访问时就会有链表移动操做,进而下降 Redis 的性能。
因而,Redis 对 LRU 的实现进行了一些改变:
config set maxmemory-samples 100
命令来配置)LFU 全称 Least Frequently Used,即最不常常使用策略,它是基于数据访问次数来淘汰数据的,在 Redis 4.0 时添加进来。它在 LRU 策略基础上,为每一个数据增长了一个计数器,来统计这个数据的访问次数。
前面说到,LRU 使用了 RedisObject 中的 lru 字段记录时间戳,lru 是 24bit 的,LFU 将 lru 拆分为两部分:
使用 LFU 策略淘汰缓存时,会把访问次数最低的数据淘汰,若是访问次数相同,再根据访问的时间,将访问时间戳最小的淘汰。
为何 Redis 有了 LRU 还须要 LFU 呢?
在一些场景下,有些数据被访问的次数很是少,甚至只会被访问一次。当这些数据服务完访问请求后,若是还继续留存在缓存中的话,就只会白白占用缓存空间。
因为 LRU 是基于访问时间的,若是系统对大量数据进行单次查询,这些数据的 lru 值就很大,使用 LFU 算法就不容易被淘汰。