Redis是一个高性能的内存缓存系统,由于内存大小有限,缓存系统必须遵循一些过期策略和淘汰策略来删除一些不再需要的KEY,以便为新KEY腾出空间。
过期策略
- 定时扫描,删除过期数据,默认每秒10次;
- 惰性删除,当访问一个 key 时,如果该 key 过期,则删除,返回数据不存在。
Redis同时使用惰性过期+定期过期两种过期策略。
定期删除
Redis 会将每个设置了过期时间的key放入到一个独立的字典中,以后会定期遍历这个字典来删除到期的 key,Redis默认会每秒10次过期扫描(redis.conf 进行配置:hz 10),过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。
1. 从过期字典中随机 20 个 key;
2. 删除这 20 个 key 中已经过期的 key;
3. 如果过期的 key比率超过25%,那就重复步骤 1;
Redis默认是每隔 100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。假如 Redis 存了几十万个key,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载。
- 优点
通过限制删除操作的时长和频率,来减少删除操作对 Redis 主业务的影响,同时也能删除一部分过期的数据减少了过期键对空间的无效占用。 - 缺点
定期删除可能会导致很多过期key到了时间并没有被删除掉。
惰性删除
惰性策略就是在客户端访问这个key的时候,Redis对key的过期时间进行检查,如果过期了就立即删除,并返回空。
- 优点
因为每次访问时,才会判断过期键,所以此策略只会使用很少的系统资源。 - 缺点
系统占用空间删除不及时,导致空间利用率降低,造成了一定的空间浪费。
内存淘汰策略
- volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
- volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
- volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
- volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
- allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。
- allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
- allkeys-random:从数据集中任意选择数据淘汰。
- no-enviction:禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失。
其中LRU、LFU 算法
LRU(least recently used): 最近最少使用算法
LFU(Least Frequently Used): 最不经常使用淘汰算法
内存淘汰策略最佳实践
- 数据访问频率差异大(冷热数据区分明显)优先使用 allkeys-lru 策略
- 数据访问频率差异不大时(无明显冷热数据区分)推荐使用 allkeys-random 策略
- 业务有置顶需求(置顶新闻、视频)使用 volatile-lru策略,并对指定数据不设置过期时间