2024年最全后端面试每日一题 Redis 的过期策略和内存淘汰机制,系统架构师面试经验

最后

手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友

image.png

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

需要这份系统化的资料的朋友,可以点击这里获取

int keyIsExpired(redisDb *db, robj *key) {

mstime_t when = getExpire(db,key);

if (when < 0) return 0;

if (server.loading) return 0;

mstime_t now = server.lua_caller ? server.lua_time_start : mstime();

return now > when;

}

// 获取键的过期时间

long long getExpire(redisDb *db, robj *key) {

dictEntry *de;

if (dictSize(db->expires) == 0 ||

(de = dictFind(db->expires,key->ptr)) == NULL) return -1;

serverAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);

return dictGetSignedIntegerVal(de);

}

惰性删除的执行流程如下图所示:

img

除了惰性删除之外,Redis 还提供了定期删除功能以弥补惰性删除的不足。

定期删除是指 Redis 服务器每隔一段时间会检查一下数据库,看看是否有过期键可以被清除。

默认情况下 Redis 定期检查的频率是每秒扫描 10 次,用于定期清除过期键。当然此值还可以通过配置文件进行设置,在 redis.conf 中修改配置“hz”即可,默认的值为“hz 10”。

小贴士:定期删除的扫描并不是遍历所有的键值对,这样的话比较费时且太消耗系统资源。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 的内存淘汰策略,示例代码如下:

最后

既已说到spring cloud alibaba,那对于整个微服务架构,如果想要进一步地向上提升自己,到底应该掌握哪些核心技能呢?

就个人而言,对于整个微服务架构,像RPC、Dubbo、Spring Boot、Spring Cloud Alibaba、Docker、kubernetes、Spring Cloud Netflix、Service Mesh等这些都是最最核心的知识,架构师必经之路!下图,是自绘的微服务架构路线体系大纲,如果有还不知道自己该掌握些啥技术的朋友,可根据小编手绘的大纲进行一个参考。

image

如果觉得图片不够清晰,也可来找小编分享原件的xmind文档!

且除此份微服务体系大纲外,我也有整理与其每个专题核心知识点对应的最强学习笔记:

  • 出神入化——SpringCloudAlibaba.pdf

  • SpringCloud微服务架构笔记(一).pdf

  • SpringCloud微服务架构笔记(二).pdf

  • SpringCloud微服务架构笔记(三).pdf

  • SpringCloud微服务架构笔记(四).pdf

  • Dubbo框架RPC实现原理.pdf

  • Dubbo最新全面深度解读.pdf

  • Spring Boot学习教程.pdf

  • SpringBoo核心宝典.pdf

  • 第一本Docker书-完整版.pdf

  • 使用SpringCloud和Docker实战微服务.pdf

  • K8S(kubernetes)学习指南.pdf

image

另外,如果不知道从何下手开始学习呢,小编这边也有对每个微服务的核心知识点手绘了其对应的知识架构体系大纲,不过全是导出的xmind文件,全部的源文件也都在此!

image

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

需要这份系统化的资料的朋友,可以点击这里获取

不过全是导出的xmind文件,全部的源文件也都在此!

[外链图片转存中…(img-Lf0Qyk24-1715106241890)]

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

需要这份系统化的资料的朋友,可以点击这里获取

  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值