【Redis】Redis过期删除策略和内存淘汰策略剖析(Redis专栏启动)

📫作者简介:小明java问道之路,专注于研究 Java/ Liunx内核/ C++及汇编/计算机底层原理/源码,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。

        

📫 热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长。

        

🏆 CSDN博客专家/后端领域优质创作者/内容合伙人、InfoQ签约作者、阿里云专家/签约博主、51CTO专家 🏆

        

🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~ 


专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

🔥MySQL从入门到精通🔥

MySQL从入门到精通

全面讲解MySQL知识与实战

🔥计算机底层原理🔥

深入理解计算机系统CSAPP

构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

🔥数据结构与企业题库精讲🔥

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

🔥互联网架构分析与实战🔥

企业系统架构分析实践与落地

行业前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

金融公司的防资损方法论、代码与实践。

本文目录

本文目录

本文导读

一、Redis 过期策略

1、三种过期策略 

1.1、定时删除

1.2、定期删除

1.3、惰性删除

2、Redis的过期策略

2.1、Redis 过期删除策略(惰性删除和定期删除)

2.2、惰性删除原理解析

2.3、如何判断 Key 是否过期

2.4、定期删除原理解析

二、内存淘汰策略

1、Redis 内存淘汰策略有哪些

2、八种Redis 内存淘汰策略

3、Redis中的LRU 算法和 LFU 算法

总结


本文导读

Redis的过期删除策略和内存淘汰策略,很容易混淆。本文分两个模块,一讲解Redis的三种过期策略以及其中原理和源码,二是讲解内存淘汰策略的八种方式和其原理。

一、Redis 过期策略

1、三种过期策略 

众所周知,Redis是一个 key-value 的键值数据库。我们可以设置缓存在Redis中的 key 的过期时间。Redis的过期策略是指当缓存在Redis中的 key 过期时,Redis将要如何处理。

过期策略通常有以下三种:定时删除、惰性删除、定期删除

1.1、定时删除

定时删除:

设置了过期时间的 key 创建一个计时器,过期后将立即清除。此策略可以立即清除过期数据,并且对内存友好;然而,它将占用大连的CPU资源来处理过期数据,从而影响缓存的响应时间和吞吐量(时间换空间)

优点:

可以保证过期 key 会被尽快删除,也就是内存可以被尽快地释放,定时删除对内存是最友好的。

缺点:

在过期 key 比较多的情况下,删除过期 key 可能会占用相当一部分 CPU 时间,在内存不紧张但 CPU 时间紧张的情况下,将 CPU 时间用于删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。所以,定时删除策略对 CPU 不友好。

1.2、定期删除

定期删除:

定期扫描特定数量数据库的过期字典中特定数据的 Key(随机检查、集中检查),并清除过期 Key。该策略是一种定时过期和延迟过期的方案,通过调整计划扫描的时间间隔和每次扫描的有限时间消耗,CPU和内存可以在不同的情况下得到最佳平衡(过期字典存储设置了过期时间的所有 Key 的过期时间数据,其中 key 是指向键空间中某个Key 的指针,value是 Key 的UNIX时间戳表示的过期时间,精度为毫秒,键空间指的是保存在Redis集群中的所有Key)。 

优点:

通过限制删除操作的持续时间和频率,可以减少删除操作对CPU的影响。同时,可以删除一些过期数据,以减少过期 Key 的无效空间占用。

缺点:

内存清理不如常规删除有效,并且在没有延迟删除的情况下使用更少的系统资源。很难确定执行删除操作的时间和频率。如果执行过于频繁,则常规删除策略与常规删除策略相同,这对CPU不友好;如果执行太少,则与延迟删除相同。过期 Key 占用的内存将无法及时释放。

1.3、惰性删除

惰性删除:

当访问 Key 时,将判断该 Key 是否已过期。如果过期,它将被清除。这种策略可以最大限度地节省CPU资源,但它非常消耗内存,而且许多过期数据仍在内存中。在极端情况下,大量过期 Key  可能无法再次访问,因此不会被清除并占用大量内存。(空间换时间) 

优点:

由于每次访问 Key 时都会检查其是否过期,因此此策略仅使用少数系统资源。因此,延迟删除策略对CPU时间最为友好。

缺点:

如果某个 Key 已过期且该 Key 仍在数据库中,则只要该过期 Key 未被访问,该过期 Key 所占用的内存就不会被释放,从而导致一定的内存空间浪费。因此,延迟删除策略对内存不友好。

2、Redis的过期策略

2.1、Redis 过期删除策略(惰性删除和定期删除)

Redis中同时使用了惰性过期和定期过期两种过期策略。

目的是为了在合理使用 CPU 时间和避免内存浪费之间取得平衡。

2.2、惰性删除原理解析

Redis的延迟删除策略由 db.c 文件中 expireIfNeeded 函数的实现。

int expireIfNeeded(redisDb *db, robj *key) {
    // 判断 key 是否过期
    if (!keyIsExpired(db,key)) return 0;
    ....
    /* 删除过期键 */
    ....
    // 如果 server.lazyfree_lazy_expire 为 1 表示异步删除,反之同步删除;
    return server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) : dbSyncDelete(db,key);
}

在访问或修改 Key 之前,Redis将调用expireIfNeeded函数来检查 Key 是否过期:如果过期,请删除 Key。至于选择异步删除还是同步删除, lazyfree_lazy_expire 参数配置决策,然后返回空客户端;如果未过期,则不进行任何处理,然后将正常的键值对返回给客户端;

2.3、如何判断 Key 是否过期

每当我们为 Key 设置过期时间时,Redis都会将 Key 与过期时间一起存储在过期字典中,也就是说,过期字典存储数据库中所有 Key 的过期时间。

字典实际上是一个哈希表。哈希表的最大优点是它允许我们以O(1)的时间复杂度搜索。当我们查询 Key 时,Redis首先检查该 Key 是否存在于过期字典中,如果没有,则正常读取键值;如果存在,将获取 Key 的过期时间,并与当前系统时间进行比较。如果大于系统时间, Key 将不会过期,否则将确定 Key 已过期。 

// 过期字典存储在 redisDb 结构中
typedef struct redisDb {
    dict *dict;    // 数据库键空间,存放着所有的键值对
    dict *expires; // 键的过期时间
    ....
} redisDb;

2.4、定期删除原理解析

定期从数据库中“随机”抽取一定数量的 Key 进行检查,并删除过期的 Key 。这种随机性可以理解为,在Redis中,默认情况下,数据库每秒钟检查一次过期10次。此配置可以通过Redis的配置文件Redis Conf完成。配置Key为hz。其默认值为hz 10。

特别强调的是,每次检查数据库时,并不是遍历过期字典中的所有键,而是从数据库中随机选择一定数量的键进行过期检查。

随机抽查的数量定期删除在expire.c 文件下的 activeExpireCycle 函数中,随机检查的数量由 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 定义。它是用代码编写的,值为20。
也就是说,在每一轮抽查中,将随机选择20个 Key 来确定数据库是否过期。

// 定期删除的流程(伪代码)
do {
    expired = 0; // 已过期的数量
    num = 20;    // 随机抽取的数量
    while (num--) {
        // 1. 从过期字典中随机抽取 1 个 key
        // 2. 判断该 key 是否过期,如果已过期则进行删除,同时对 expired++
    }
    // 超过时间限制则退出
    if (timelimit_exit) return;

  // 如果本轮检查的已过期 key 的数量,超过 25%,则继续随机抽查,否则退出本轮检查
} while (expired > 20/4); 

二、内存淘汰策略

1、Redis 内存淘汰策略有哪些

当Redis的运行内存超过Redis设置的最大内存时,将使用内存消除策略删除符合条件的密钥,以确保Redis的高效运行。

Redis使用内存存储数据。在执行每个命令之前,它调用 freeMemoryIfNeeded()  方法来检查内存是否足够。

如果内存不满足新添加数据的最低存储要求,Redis需要临时删除一些数据,以清理当前指令的存储空间。清理数据的策略也称为驱逐算法。

注意:消除数据的过程不能100%清除足够的可用内存空间。如果不成功,它将被重复。完成所有数据尝试后,如果无法满足内存清理要求,将显示错误消息。

当新数据进入redis时,如果内存不足怎么办?

1、最大可用内存:占用的物理内存的比例。默认值为0,表示没有限制。它是根据生产环境中的要求设置的,通常在50%以上。(maxmemory )

2、选择每次要删除的数据数量:选择数据时,它不会扫描整个数据库,这会导致严重的性能消耗并降低读写性能。因此,采用随机获取数据的方法作为要检测的删除数据。(maxmemory-samples)

3、删除策略:达到最大内存后,删除所选数据的策略(maxmemory-policy)会影响过时的相关配置

2、八种Redis 内存淘汰策略

1、无数据消除策略

noeviction(Redis3.0之后,默认的内存淘汰策略) :禁止驱逐数据(Redis 4.0中的默认策略),这将导致内存不足Redis驱逐策略错误。这意味着当运行内存超过最大设置内存时,不会消除任何数据,但不会提供任何服务,并且会直接返回错误。

2、进行数据淘汰的策略

对于“数据消除”策略,可以细分为两种类型:“在设置了过期时间的数据中消除”和“在所有数据范围中消除”。

消除设置了过期时间的数据:

volatile-random:可选地选择数据消除以检测整个数据库数据(所有数据集server.db[i].dice);
volatile-ttl:选择将过期的数据。
volatile-lru(Redis3.0 之前,默认的内存淘汰策略):消除所有设置了过期时间的键值,并选择最近最少使用的数据;
volatile-lfu(Redis 4.0 后新增的内存淘汰策略)消除所有设置了过期时间的键值,并选择最近使用最少的数据;

所有数据:

allkeys-random:选择任何数据以消除和放弃数据驱逐;
allkeys-lru:从整个键值中选择最近最少使用的数据;
allkeys-lfu(Redis 4.0 后新增的内存淘汰策略):消除整个键值中最近使用最少的数据。

3、Redis中的LRU 算法和 LFU 算法

参考:《从零开始的DS生活 轻松从0基础写出链表LRU算法

总结

Redis的过期删除策略和内存淘汰策略,很容易混淆。本文分两个模块,一讲解Redis的三种过期策略以及其中原理和源码,二是讲解内存淘汰策略的八种方式和其原理。

  • 11
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小 明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值