Redis 缓存过期删除/淘汰策略分析

Redis 缓存删除

  1. Redis 键过期删除,定期删除(主动)和惰性删除(被动)
  2. Redis 内存不足时,缓存淘汰策略

key 键过期删除

我们用 redis 作为缓存数据库,设置 k-v 数据的时候,可以给这条数据设置一个过期时间。比如,set 命令设置过期时间:

set testkey redisvalue EX 60

EX: 表示秒, EX 60 表示这个键值60秒后过期。

那好,现在就有一个问题了,redis 怎么检查数据缓存时间到期了?然后删除它。

想一想,检测到期数据一般有两种方法,

第一:主动检测

第二:被动检测

什么是主动?

第一种,就是每设置一个 kv 值时,给这个 kv 值设置一个定时器,给它计时,到期就删除。但是这样会给 cpu 造成很多压力。

另外一种,定期扫描 kv 值,检查到期值在删除。

什么是被动?

被动就是对这个数据有操作时候才检查它缓存时间是否到期,如果有到期,就删除。

删除步骤:

redis 会将每个设置了过期时间的 key 放到一个独立的字典集合中,以后会定时遍历这个字典来删除到期的 key。

定时遍历删除,默认情况每秒检查 10 次键的字典集合,每次从这个集合中随机检查 20 个键查看是否过期,过期就直接删除。删除后还有超过 25% 的集合中键过期,继续随机抽取 20 个键检测删除。

还有惰性删除,就是在客户端访问这个 key 时,redis 会对 key 的过期时间进行检查,过期了就删除。

Redis 内存不足时缓存淘汰策略

redis 的 8 种缓存淘汰策略

redis.conf 配置文件中,就可以看到 redis 缓存过期淘汰的设置项。

当 Redis 内存快要满的时候,redis 会执行缓存淘汰策略。

https://github.com/redis/redis/blob/6.2/redis.conf#L994

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select one from the following behaviors:
#
# volatile-lru -> Evict using approximated LRU, only keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU, only keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key having an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
#
# The default is:
#
# maxmemory-policy noeviction

redis v6.2 版本配置。

maxmemory , redis 提供了一个配置参数来设置 maxmemory(redis 最大可使用内存),这个参数来限制最大内存使用,实际内存超出了这个参数设置时,redis 就根据 maxmemory-policy 的设置策略删除键值,释放内存空间。

maxmemory-policy 设置,也就是内存淘汰策略,从 redis4.0 开始有8种缓存淘汰策略:

noeviction:默认设置。如果设置的空间满了,不会删除任何值,写操作请求时服务器直接返回错误。读、删除请求可以继续服务。

volatile-lru:淘汰设置了过期时间的 key,使用 lru 算法,最近最少使用的 key 先淘汰。注意,没有设置过期时间的 key 就不淘汰。why?我们是不是还有一些持久化 key 的需求。

allkeys-lru:上面 volatile-lru 是部分淘汰 key(设置了过期时间的 key)。而这个是淘汰所有的 key,不管有没有设置过期时间,都会淘汰。也是使用 lru 最近最少使用算法。

volatile-lfu:淘汰设置了过期时间的 key,使用 lfu 算法,使用频率最少的 key 先淘汰。

allkeys-lfu:淘汰所有的 key,根据 lfu 算法。

volatile-random:淘汰设置了过期时间的 key,随机算法。

allkeys-random:淘汰所有的 key,不管是否设置过期时间,随机算法。

volatile-ttl:淘汰设置了过期时间的 key,根据 key 的 ttl 剩余时间,也就是说 ttl 越小越先被淘汰。

说明:使用 lfu 淘汰算法的都是 redis4.0 以上版本。

缓存淘汰算法

  • lru:Least Recently Used,最近最少使用。
  • lfu:Least Frequently Used,使用频率最少的,最不经常使用。
  • random:随机算法。
  • ttl:根据 key 设置的 ttl 剩余时间。

random 和 ttl 这 2 种缓存淘汰算法容易理解。

但是 lru 和 lfu 不容易理解,他们的区别是什么呢?

LRU :

Least Recently Used,最近最少使用,与使用的最后一次时间有关,淘汰最近使用、时间离现在最久的。

算法思想:

如果一个数据最近一段时间没有被访问到,那么以后它被访问到的可能性也比较小。

LFU :

Least Frequently Used,最近一段时间使用频率最少,与使用的次数有关,淘汰使用次数最少的。

LFU 是 redis4.0 以后才出现的,4.0 以前都是 LRU。那 LFU 解决的是什么问题呢?

看下面的图,来自 antirez 博客文章 Random notes on improving the Redis LRU algorithm:

~~~~~A~~~~~A~~~~~A~~~~A~~~~~A~~~~~A~~|
~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~|
~~~~~~~~~~C~~~~~~~~~C~~~~~~~~~C~~~~~~|
~~~~~D~~~~~~~~~~D~~~~~~~~~D~~~~~~~~~D|

每个波浪代表 1 秒,key A 每 5 秒访问一次,key B 每 2 秒访问一次,key C 和 key D 每 10 秒访问一次。"|" 表示访问结束。

看图,从结束 "|" 位置看(实际是以时间为标准看),D 是最近一次访问。但是,从上图整体来看, B 是使用次数最多,也就是访问频率最多。如果需要淘汰的话,应该淘汰 D 才合理,LFU 才是比较合理的策略。

如果是在一段时间内,数据使用频率更高的场景中,那么 LFU 算法比 LRU 算法命中率更高。

参考

Redis 缓存过期删除/淘汰策略分析的更多相关文章

  1. Redis数据过期和淘汰策略详解(转)

    原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...

  2. Redis(二十):Redis数据过期和淘汰策略详解(转)

    原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...

  3. Redis中的LRU淘汰策略分析

    Redis作为缓存使用时,一些场景下要考虑内存的空间消耗问题.Redis会删除过期键以释放空间,过期键的删除策略有两种: 惰性删除:每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除 ...

  4. Redis: 缓存过期、缓存雪崩、缓存穿透、缓存击穿(热点)、缓存并发(热点)、多级缓存、布隆过滤器

    Redis: 缓存过期.缓存雪崩.缓存穿透.缓存击穿(热点).缓存并发(热点).多级缓存.布隆过滤器 2019年08月18日 16:34:24 hanchao5272 阅读数 1026更多 分类专栏: ...

  5. C# Redis缓存过期实现延迟通知实战演练

    一.场景描述 在实际开发过程中经常会遇到一些有时效性数据的业务场景,比如订单支付处理超时提醒.当用户在商城上进行下单支付,我们假设如果8小时没有进行支付,那么就后台自动对该笔交易的状态修改为订单关闭取 ...

  6. Redis过期key淘汰策略

    Redis采用惰性+定期的key淘汰策略 1. Redis配置项hz定义了serverCron任务的执行周期,默认为10,即CPU空闲时每秒执行10次; 2. 每次过期key清理的时间不超过CPU时间 ...

  7. Redis++:Redis 内存爆满 之 淘汰策略

    前言: 我们的redis使用的是内存空间来存储数据的,但是内存空间毕竟有限,随着我们存储数据的不断增长,当超过了我们的内存大小时,即在redis中设置的缓存大小(maxmeory 4GB),redis ...

  8. Redis之key的淘汰策略

    淘汰策略概述 redis作为缓存使用时,在添加新数据的同时自动清理旧的数据.这种行为在开发者社区众所周知,也是流行的memcached系统的默认行为. redis中使用的LRU淘汰算法是一种近似LRU ...

  9. Redis系列之-—内存淘汰策略(笔记)

    一.Redis ---获取设置的Redis能使用的最大内存大小 []> config get maxmemory ) "maxmemory" ) " --获取当前内 ...

  10. 基于Python项目的Redis缓存消耗内存数据简单分析(附详细操作步骤)

    目录 1 准备工作 2 具体实施   1 准备工作 什么是Redis? Redis:一个高性能的key-value数据库.支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使 ...

随机推荐

  1. [转帖]Intel AVX 系列指令基础介绍

    https://zhuanlan.zhihu.com/p/437657452 一.发展背景 1993年,Intel公司推出了奔腾处理器,该类型处理器拥有两条执行流水线,和当时的处理器相比,可以同时执行 ...

  2. Whisper对于中文语音识别与转写中文文本优化的实践(Python3.10)

    阿里的FunAsr对Whisper中文领域的转写能力造成了一定的挑战,但实际上,Whisper的使用者完全可以针对中文的语音做一些优化的措施,换句话说,Whisper的"默认"形态 ...

  3. vue3逻辑分离和页面快速展示数据

    逻辑分层 我们在使用vue3开发项目的时候, 如何进行[区域分层]呢???? 举一个简单的小粒子 一个区域有[查询逻辑.修改后的保存逻辑.新增逻辑.删除逻辑] 这个页面可能还有其他的区域.A区域.B区 ...

  4. 兄弟组件互相传递值-this.$bus.$emit与this.$bus.$on

    B组件向C组件传递一个值. 一种组件间通信的方式, 适用于任意的组件间通信. 适用于任意的组件间通信. 适用于任意的组件间通信. 通过this.$bus.$emit('事件名',数据)进行提供数据 通 ...

  5. docker容器中部署 kafka 和 elk

    1.下载zookeeper docker pull wurstmeister/zookeeper 2.下载kafka docker pull wurstmeister/kafka:2.11-0.11. ...

  6. C语言输出狗头

    使用printf()函数输出样式 #include <stdio.h> int main() { printf(" * ii. ;9ABH,\n"); printf(& ...

  7. 给python脚本传递命令行参数

    记录一下给python脚本传参数的几种方式 最简单的方式 在cmd/bat脚本中调用python脚本传递参数 #传递参数 python test.py arg1 arg2 arg3 #在python中 ...

  8. 3.1 C++ STL 双向队列容器

    双向队列容器(Deque)是C++ STL中的一种数据结构,是一种双端队列,允许在容器的两端进行快速插入和删除操作,可以看作是一种动态数组的扩展,支持随机访问,同时提供了高效的在队列头尾插入和删除元素 ...

  9. MySQL 之多表连查(精简笔记)

    MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RD ...

  10. Yarp 与 Nginx性能大比拼不出所料它胜利了!

    Yarp 与 Nginx 性能大比拼 测试环境: Ubuntu 22.04.3 LTS (GNU/Linux 6.5.0-14-generic x86_64) Intel(R) Xeon(R) CPU ...