Redian新闻
>
Redis的数据清理策略详解

Redis的数据清理策略详解

公众号新闻

来源 | OSCHINA 社区

作者 | KL博主

原文链接:https://my.oschina.net/klblog/blog/10110344

背景

摸清 Redis 的数据清理策略,给内存使用高的被动缓存场景,在遇到内存不足时,么做是最优解提供决策依据。 

本文整理 Redis 的数据清理策略所有代码来自 Redis version :5.0, 不同版本的 Redis 策略可能有调整

清理策略

Redis 的清理策略,总结概括为三点,被动清理、定时清理、驱逐清理

被动清理

访问 Key 时,每次都会检查该 Key 是否已过期,如果过期则删除该 Key ,get 、scan 等指令都会触发 Key 的过期检查。

关键代码如下, expireIfNeeded (redisDb *db, robj *key) 函数会触发检查并删除

robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
robj *val;

if (expireIfNeeded(db,key) == 1) {
/* Key expired. If we are in the context of a master, expireIfNeeded()
* returns 0 only when the key does not exist at all, so it's safe
* to return NULL ASAP. */

if (server.masterhost == NULL) {
server.stat_keyspace_misses++;
return NULL;
}
if (server.current_client &&
server.current_client != server.master &&
server.current_client->cmd &&
server.current_client->cmd->flags & CMD_READONLY)
{
server.stat_keyspace_misses++;
return NULL;
}
}
val = lookupKey(db,key,flags);
if (val == NULL)
server.stat_keyspace_misses++;
else
server.stat_keyspace_hits++;
return val;
}

定时清理

通过 serverCron 定期触发清理,可以通过 hz 参数,配置每秒执行多少次清理任务,流程如下
  • 1、Redis 配置项 hz 定义了 serverCron 任务的执行周期,默认为 10,即 CPU 空闲时每秒执行 10 次

  • 2、每次过期 Key 清理的 timelimit 不超过 CPU 时间的 25% ,即若 hz = 1,则一次清理时间最大为 250ms,若 hz = 10,则一次清理时间最大为 25ms,计算逻辑(timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;)

  • 3、清理时依次遍历所有的 db;

  • 4、从 db 中随机取 20 个 key,判断是否过期,若过期,则逐出;

  • 5、若有 5 个以上 key 过期,则重复步骤 4,否则遍历下一个 db;

  • 6、在清理过程中,若达到了 timelimit 时间,退出清理过程;

关键代码如下,activeExpireCycle (int type) 会执行上述逻辑
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
...
databasesCron();
...
}

void databasesCron(void) {
/* Expire keys by random sampling. Not required for slaves
* as master will synthesize DELs for us. */

if (server.active_expire_enabled) {
if (server.masterhost == NULL) {
activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);
} else {
expireSlaveKeys();
}
}
...
}
ps: activeExpireCycle 还会在主事件循环 eventLoop 中被调用,此时 type = ACTIVE_EXPIRE_CYCLE_FAST, 控制了最多执行 timelimit = 1000us 的快速清理,也会删除部分 Key 。 

驱逐清理

Redis 在命令处理函数 processCommand 会进行内存的检查和驱逐,任何命令都会出触发,包括 ping 命令。
  • 如果配置了 maxmemory ,且当前内存超过 maxmemory 时,则会执行 maxmemory_policy 筛选出需要清理的 Key,继而判断 lazyfree-lazy-eviction 是否开启来进行 Key 的同步还是异步删除。无论是同步删除还是异步删除,最后都会继续校验内存是否超限,直到内存低于 maxmemory。驱逐只会在 Master 节点进行。

maxmemory_policy 可选如下:
  • volatile-lru:从已设置过期时间的数据集中挑选【最近最少使用】的 Key 进行删除

  • volatile-ttl:从己设置过期时间的数据集中挑选【将要过期】的 Key 进行删除

  • volatile-lfu:从己设置过期时间的数据集中选择【最不常用】的 Key 进行删除

  • volatile-random:从己设置过期时间的数据集中【任意选择】Key 进行删除

  • allkeys-lru:从数据集中挑选【最近最少使用】的 Key 进行删除

  • allkeys-lfu:从数据集中【优先删除掉最不常用】的 Key

  • allkeys-random:从数据集中【任意选择】 Key 进行删除

  • no-enviction:禁止驱逐数据

如上图,6.2 后的版本支持通过逐出因子 maxmemory-eviction-tenacity 来控制逐出阻塞的时间。具体的阻塞耗时间可以通过 latency-monitor 里的 eviction-cycleeviction-del 来观测。
关键代码如下,freeMemoryIfNeeded () 函数会执行上述逻辑
int processCommand(client *c) {
...
if (server.maxmemory && !server.lua_timedout) {
int out_of_memory = freeMemoryIfNeededAndSafe() == C_ERR;
...
}
...
}

int freeMemoryIfNeededAndSafe(void) {
if (server.lua_timedout || server.loading) return C_OK;
return freeMemoryIfNeeded();
}

ps: 当触发 aof 文件重写,fork 操作会阻塞主进程,此时积压的指令需要的内存,在 fork 结束后,需要一次性 eviction 出来,这时的 eviction-cycle 耗时会恶化的很严重,达到秒级的阻塞,此时可通过 latency-monitor 观测 eviction-cycle 、fork 总是成对出现。

总结

回到开篇的背景问题,当遇到内存使用高的被动缓存场景,可用内存不足时:

  • 离线分析内存,是否存在大量【已过期】的内存来不及定时清理,此时可调大 hz 参数来加速过期内存的主动清理。hz 参数最大 500 ,不过要观察 CPU 的影响,不要因为 hz 影响读写流量

  • 如果调整 hz 还是没法及时清理已过期的内存,则可以使用 scan 指令来被动访问 key 的方式手动删除,注意执行 scan 时的 count ,同时观测 CPU 使用情况,scan 的 count 越大,CPU 消耗会越高,完成一次 sacn 删除的时间最快。为了减少对线上的影响,可以在业务低峰期,周期性的执行。

  • 通过 latency-monitor 观测 eviction-cycle、eviction-del 指标,是否因内存驱逐阻塞严重,可开启 lazyfree-lazy-eviction 来缓解阻塞。

  • 业务上可以考虑关闭 aof 的影响,关闭 aof 可以减少驱逐清理 eviction-cycle 延迟带来的读写超时影响。

  • 可升级到 7.x 版本的 Redis ,通过 maxmemory-eviction-tenacity 参数主动控制每次驱逐的阻塞时间

  • 如果还是很慢,可考虑升级内存规格

参考:

  • 快手 Redis 架构演进实践_脱敏.pdf


END



iphone 15 Pro Max 设计过程大公开



这里有最新开源资讯、软件更新、技术干货等内容

点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦


微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
《花尾渡》(小说) 第十六章 豪情尽洒南京路No Pre-entry COVID Test RequiredChanticleer花园,溪水潺潺人类创造的数据太贵了!开发者悄悄使用AI合成数据训练模型Redmi首款曲面屏来了!Redmi Note 13 系列定档9月21日发布Good News For Cold Noodle Lovers: License Requirements Relaxed部分旧版Chase Freedom用户被强制“暖心升级”成Chase Freedom UnlimitedHow Korea Quietly Reshaped Chinese Pop Culture不公布数据,或许会得到更准确的数据许静教授:无症状房颤与症状房颤的处理策略是否应有所区别?| GW-ICC 2023ChatGPT 和 OpenAI 都在用的 Redis,是如何从传统数据库升级为向量数据库的?Rescue Teams Struggle to Reach Isolated Areas in Flood-Hit Hebei「柏川数据」获千万元天使轮融资,强化以自动化标注为核心的数据智能服务|早起看早期Troubled Singing Reality Show Accused of Mistreating Coco Lee【广发策略戴康团队】全市场最全策略数据库:八位一体数据库真假?GRE optional跟required没区别?重新审视高血压性心脏病,这些新兴诊断和管理策略你了解吗?马上抢位|《数据科学·机器学习求职实战营》明日开课,全方位提升你的数据分析综合能力!Redmi K60 Pro或已停产,Redmi K60 Ultra蓄势待发Deadly School Stampede Renews Calls For Scheduling Reform人类已进入大数据时代, 这个职业潜力无限! 西澳大学数据科学硕士详解「柏川数据」获千万元天使轮融资,强化以自动化标注为核心的数据智能服务|36氪首发说服力的科学:《影响力》的六大心理策略“我的健康,我的数据法案”:美国的健康数据立法最“性感”的职业,大数据时代下爆火的数据科学!行业薪资,就业前景,专业申请大揭秘基础模型自监督预训练的数据之谜:大量数据究竟是福还是祸?How a Red-Haired Chatbot Became China’s Favorite English Tutor不负人生·生命之赛(The Race of A Lifetime)蔡L先生有活不过50岁的家族史?这是家族性ALS的大数据分析及可能的研究方案历史小说《黄裳元吉》第一百一十八章 黑云首个Unified Redis Release,Redis影响最深远的版本发布财宝逛酒庄哈佛认证:这张可挂LinkedIn的数据分析证书,留学生7天可拿Hundreds of Chinese Arrested For Cyberscams in Laos, Myanmar澳洲推出免费新服务MyMedicare!有什么好处?是否应该注册?一文详解!
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。