后端面试每日一题 Redis 的过期策略和内存淘汰机制

文章详细介绍了Redis服务器如何通过随机抽查的方式高效处理过期键,并设置最大执行时间防止线程阻塞。同时,对比了过期策略和内存淘汰策略的区别。此外,还提及了Java工程师的学习资源和面试准备
摘要由CSDN通过智能技术生成

小贴士:定期删除的扫描并不是遍历所有的键值对,这样的话比较费时且太消耗系统资源。Redis 服务器采用的是随机抽取形式,每次从过期字典中,取出 20 个键进行过期检测,过期字典中存储的是所有设置了过期时间的键值对。如果这批随机检查的数据中有 25% 的比例过期,那么会再抽取 20 个随机键值进行检测和删除,并且会循环执行这个流程,直到抽取的这批数据中过期键值小于 25%,此次检测才算完成。

定期删除的源码在 expire.c 文件的 activeExpireCycle 方法中,如下所示:

void activeExpireCycle(int type) {

static unsigned int current_db = 0; /* 上次定期删除遍历到的数据库ID */

static int timelimit_exit = 0;

static long long last_fast_cycle = 0; /* 上次执行定期删除的时间点 */

int j, iteration = 0;

int dbs_per_call = CRON_DBS_PER_CALL; // 需要遍历数据库的数量

long long start = ustime(), timelimit, elapsed;

if (clientsArePaused()) return;

if (type == ACTIVE_EXPIRE_CYCLE_FAST) {

if (!timelimit_exit) return;

// ACTIVE_EXPIRE_CYCLE_FAST_DURATION 快速定期删除的执行时长

if (start < last_fast_cycle + ACTIVE_EXPIRE_CYCLE_FAST_DURATION*2) return;

last_fast_cycle = start;

}

if (dbs_per_call > server.dbnum || timelimit_exit)

dbs_per_call = server.dbnum;

// 慢速定期删除的执行时长

timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;

timelimit_exit = 0;

if (timelimit <= 0) timelimit = 1;

if (type == ACTIVE_EXPIRE_CYCLE_FAST)

timelimit = ACTIVE_EXPIRE_CYCLE_FAST_DURATION; /* 删除操作花费的时间 */

long total_sampled = 0;

long total_expired = 0;

for (j = 0; j < dbs_per_call && timelimit_exit == 0; j++) {

int expired;

redisDb *db = server.db+(current_db % server.dbnum);

current_db++;

do {

// …

expired = 0;

ttl_sum = 0;

ttl_samples = 0;

// 每个数据库中检查的键的数量

if (num > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)

num = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;

// 从数据库中随机选取 num 个键进行检查

while (num–) {

dictEntry *de;

long long ttl;

if ((de = dictGetRandomKey(db->expires)) == NULL) break;

ttl = dictGetSignedInteger

// 过期检查,并对过期键进行删除

if (activeExpireCycleTryExpire(db,de,now)) expired++;

if (ttl > 0) {

ttl_sum += ttl;

ttl_samples++;

}

total_sampled++;

}

total_expired += expired;

if (ttl_samples) {

long long avg_ttl = ttl_sum/ttl_samples;

if (db->avg_ttl == 0) db->avg_ttl = avg_ttl;

db->avg_ttl = (db->avg_ttl/50)*49 + (avg_ttl/50);

}

if ((iteration & 0xf) == 0) { /* check once every 16 iterations. */

elapsed = ustime()-start;

if (elapsed > timelimit) {

timelimit_exit = 1;

server.stat_expired_time_cap_reached_count++;

break;

}

}

/* 判断过期键删除数量是否超过 25% */

} while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);

}

// …

}

定期删除的执行流程,如下图所示:

img

小贴士:Redis 服务器为了保证过期删除策略不会导致线程卡死,会给过期扫描增加了最大执行时间为 25ms。

以上是 Redis 服务器对待过期键的处理方案,当 Redis 的内存超过最大允许的内存之后,Redis 会触发内存淘汰策略,这和过期策略是完全不同的两个概念,经常有人把二者搞混,这两者一个是在正常情况下清除过期键,一个是在非正常情况下为了保证 Redis 顺利运行的保护策略。

当 Redis 内存不够用时,Redis 服务器会根据服务器设置的淘汰策略,删除一些不常用的数据,以保证 Redis 服务器的顺利运行。

Redis 内存淘汰策略

我们可以使用 config get maxmemory-policy 命令,来查看当前 Redis 的内存淘汰策略,示例代码如下:

127.0.0.1:6379> config get maxmemory-policy

  1. “maxmemory-policy”

  2. “noeviction”

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

总结

对于面试,一定要有良好的心态,这位小伙伴面试美团的时候没有被前面阿里的面试影响到,发挥也很正常,也就能顺利拿下美团的offer。
小编还整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家,

在这里插入图片描述

在这里插入图片描述

最后感谢大家的支持,希望小编整理的资料能够帮助到大家!也祝愿大家都能够升职加薪!

试美团的时候没有被前面阿里的面试影响到,发挥也很正常,也就能顺利拿下美团的offer。
小编还整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家,

[外链图片转存中…(img-urr7SmWF-1710752618248)]

[外链图片转存中…(img-xmWoi8hP-1710752618248)]

最后感谢大家的支持,希望小编整理的资料能够帮助到大家!也祝愿大家都能够升职加薪!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值