【🔥🔥🔥Redis 内存管理核心】过期键删除策略与内存淘汰机制详解
Redis 的过期键删除策略和内存淘汰策略是其管理内存、防止内存耗尽的关键机制,它们解决的是不同层面的问题:
一、过期键删除策略
目标是自动删除那些设置了过期时间且已过期的键,释放其占用的内存。Redis 采用两种策略协同工作:
惰性删除
- 原理: 当客户端尝试访问一个键时,Redis 会先检查这个键是否设置了过期时间以及是否已过期。
- 操作: 如果键已过期,Redis 会立即删除这个键,然后才执行客户端的访问命令(返回
nil或执行失败)。 - 优点: 对 CPU 时间友好。只有在真正访问到过期键时才付出删除的成本。没有访问的过期键即使存在,也不会消耗额外的 CPU 去删除它们。
- 缺点: 对内存不友好。如果一个键设置了过期时间但之后再也没有被访问过,那么它会一直占用内存空间,直到被访问或者被定期删除策略扫描到并删除。这相当于一种“内存泄漏”。
定期删除
- 原理: Redis 会周期性地、主动地从设置了过期时间的键集合中随机抽取一部分键(默认每次检查 20 个键),检查它们是否过期。
- 操作:
- 每次执行时,从过期字典中随机选择一定数量的键。
- 删除其中所有已过期的键。
- 如果发现本次检查中过期的键比例超过一定阈值(默认是 25%),则立即再随机抽取一批键进行检查(循环),直到过期键比例降到阈值以下或达到时间限制(避免过度占用 CPU)。
- 优点: 一定程度上减少了惰性删除带来的内存浪费问题,通过周期性扫描清理掉那些长期不被访问的过期键。
- 缺点: 需要平衡扫描的频率、每次扫描的数量以及 CPU 消耗。扫描太频繁或每次扫描太多键会消耗过多 CPU;扫描太少或太慢则可能导致大量过期键堆积。它是一个折中方案,无法保证实时删除所有过期键。
总结: Redis 通过惰性删除 + 定期删除的组合策略来管理过期键。惰性删除确保访问时数据是最新的且能释放内存;定期删除则像一个“清洁工”,定期清理那些“僵尸”过期键,减少内存占用。两者互补,但都无法保证绝对实时删除所有过期键。
二、内存淘汰策略
目标是当 Redis 使用的内存达到
maxmemory配置的限制时,Redis 如何选择要删除哪些键(无论是否过期)来释放空间,以便写入新数据。这是防止 Redis 因内存耗尽而崩溃的最后一道防线。
Redis 提供了 8 种内存淘汰策略,通过 maxmemory-policy 配置项指定:
noeviction:默认策略。当内存不足时,新写入操作会报错(如(error) OOM command not allowed when used memory > 'maxmemory')。读操作通常不受影响。适用于你确信数据绝对不能丢失且宁愿拒绝写入也不能覆盖数据的场景。allkeys-lru:从所有键空间中,使用 LRU 算法淘汰最近最少使用的键。这是最常用且通常效果较好的策略。volatile-lru:从设置了过期时间的键空间中,使用 LRU 算法淘汰最近最少使用的键。allkeys-lfu:从所有键空间中,使用 LFU 算法淘汰最不经常使用的键(根据访问频率)。适用于访问模式随时间变化较大的场景。volatile-lfu:从设置了过期时间的键空间中,使用 LFU 算法淘汰最不经常使用的键。allkeys-random:从所有键空间中,随机淘汰任意键。volatile-random:从设置了过期时间的键空间中,随机淘汰任意键。volatile-ttl:从设置了过期时间的键空间中,淘汰剩余生存时间最短的键。即优先淘汰即将过期的键。
关键点说明
- 作用时机: 仅当内存使用达到
maxmemory限制且客户端尝试执行会增加内存使用量的命令(如SET,LPUSH,HINCRBY等)时触发淘汰。 - 作用范围: 以
allkeys-开头的策略会淘汰所有键(包括未设置过期时间的键)。以volatile-开头的策略只淘汰设置了过期时间的键。 volatile-lru/volatile-lfu/volatile-random/volatile-ttl的特殊情况: 如果内存不足时,淘汰池(设置了过期时间的键)中没有合适的键可淘汰(例如没有键设置过期时间),那么这些策略的行为会退化成noeviction,新写入操作会报错。- LRU vs LFU:
- LRU (Least Recently Used): 关注“最近使用时间”。认为最近没被用过的键将来也不太可能被用到。实现上是近似 LRU(采样)。
- LFU (Least Frequently Used): 关注“访问频率”。认为访问次数最少的键将来也不太可能被用到。Redis 实现的 LFU 会随时间衰减访问计数(避免旧热点数据长期霸占)。
- 选择策略:
- 如果数据访问模式接近 LRU,或者不确定,
allkeys-lru通常是最佳选择。 - 如果数据有明显的热点和冷门区分,且热点访问频繁,
allkeys-lfu可能更好。 - 如果你希望 Redis 只作为缓存使用(数据可丢失),所有键都设置了过期时间,并且希望优先淘汰快过期的数据,可以用
volatile-ttl。 - 如果你有部分持久化数据(不能淘汰)和部分缓存数据(可淘汰),确保缓存数据都设置了过期时间,然后使用
volatile-lru或volatile-lfu。 noeviction适用于数据绝对不能丢失的场景(但要做好容量规划和监控)。allkeys-random和volatile-random通常效果不如基于 LRU/LFU 的策略,除非你的访问模式是完全随机的。
- 如果数据访问模式接近 LRU,或者不确定,
总结: 内存淘汰策略是 Redis 在内存耗尽时的应急机制,用于释放空间以允许新数据写入。你需要根据数据的特性(是否可丢失、访问模式、是否都设过期时间)来谨慎选择合适的策略。allkeys-lru 或 allkeys-lfu 是最常用和推荐的通用策略。务必配置 maxmemory 并根据需要设置 maxmemory-policy。
【🔥🔥🔥Redis 内存管理核心】过期键删除策略与内存淘汰机制详解的更多相关文章
- 【Redis】过期键删除策略和内存淘汰策略
Redis 过期键策略和内存淘汰策略 目录 Redis 过期键策略和内存淘汰策略 设置Redis键过期时间 Redis过期时间的判定 过期键删除策略 定时删除 惰性删除 定期删除 Redis过期删除策 ...
- redis中key的过期键删除策略
Redis过期键删除策略 Redis key过期的方式有三种: 被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key 主动删除:由于惰性删除策略无法保证冷数据被及时删 ...
- redis的3种过期键删除策略
Redis的过期键的过期时间都保存在过期字典中,过期键的删除策略有三种,分别是定时删除.惰性删除和定期删除. 定时删除 定时删除策略,是指在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时 ...
- 一文了解:Redis过期键删除策略
Redis过期键删除策略 Redis中所有的键都可以设置过期策略,就像是所有的键都可以上"生死簿",上了生死簿的键到时间后阎王就会叉掉这个键.同一时间大量的键过期,阎王就会忙不过来 ...
- Redis系列(五):Redis的过期键删除策略
本篇博客是Redis系列的第5篇,主要讲解下Redis的过期键删除策略. 本系列的前4篇可以点击以下链接查看: Redis系列(一):Redis简介及环境安装 Redis系列(二):Redis的5种数 ...
- Redis的过期键删除策略
文章首发于公众号:蘑菇睡不着,欢迎来看看 前言 Redis 中都是键值对的存储形式,键都是字符串类型的,而值有很多种类型,如 string.list.hash.set.sorted set等类型.当设 ...
- Redis 过期键删除策略
Redis 中数据库键的过期时间都保存在过期字典中,当一个键过期了,Redis 存在三种不同的删除策略:定时删除.惰性删除和定期删除 定时删除 定义 在设置键的过期时间的同时创建一个计时器,让定时器在 ...
- Redis 内存淘汰机制详解
一般来说,缓存的容量是小于数据总量的,所以,当缓存数据越来越多,Redis 不可避免的会被写满,这时候就涉及到 Redis 的内存淘汰机制了.我们需要选定某种策略将"不重要"的数据 ...
- redis过期键删除策略以及大key删除方法
今天遇到了一个前同事挖的坑,刷新缓存中商品信息时先让key过期,然后从数据库里取最新数据然后再放到缓存中,他是这样写的 redisTemplate.expire(CacheConst.GOOGS_PR ...
- Redis的过期删除策略(和内存淘汰机制)-转
版权声明:本文为CSDN博主「奥修诺斯」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/qq_39944869/ ...
随机推荐
- 【笔记】Python3|(一)Python 申请并调用国内百度、阿里、腾讯、有道的翻译 API 的教程和测试情况(第三方库 translate 和 腾讯 API 篇)
var code = "dccf4c95-7458-4b38-b8ae-d45b3e59c218" 价格和 API 申请参考: 免费翻译接口最新最全汇总(百度翻译,腾讯翻译,谷歌翻 ...
- 【记录】JS和C++的Base64编码解码(支持中文)
JS 解决方法来源于知乎新码笔记的文章 function b64Encode(str) { return btoa(unescape(encodeURIComponent(str))); } func ...
- Java的"伪泛型"变"真泛型"后,会对性能有帮助吗?
泛型存在于Java源代码中,在编译为字节码文件之前都会进行泛型擦除(type erasure),因此,Java的泛型完全由Javac等编译器在编译期提供支持,可以理解为Java的一颗语法糖,这种方式实 ...
- vue3 基础-non-props 特性
本篇探讨当父组件通过属性给子组件传数据时, 子组件如果不通过 props 属性进行接收, 那数据会挂载到哪里, 以及子组件如何能使用这些数据. 正常的父子组件传值 <!DOCTYPE html& ...
- 掌握Node.js原理,开启异步编程之旅
@charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...
- linux里面的Crontab 定时任务
一.基本概念 1.1. 概念:crond 是 Linux 下用来周期地执行某种任务或等待处理某些事件的一个守护进程,和 Windows 中的计划任务有些类似. 我们经常使用的是crontab ...
- java后端http大文件传输接口笔记
笔记 接口方 package com.chinaums.demo.example.controller; import org.springframework.web.bind.annotation. ...
- 洛谷 P5066 [Ynoi2014] 人人本着正义之名debug-log
序言 此日志分为四部分. 00:00是开始打代码的时间. 最开始打完代码(没有debug)大约用了两小时. part1-20210323 02:30 生成新节点时,没有给随机权值. 02:41 upd ...
- 关于cc1链-lazymap版复现
关于cc1链-lazymap版复现 思路,在cc链中最重要的其实是transform方法;其反射调用执行的性质+transformchain性质,导致可以通过构造反射调用链子,也就是Runtime.e ...
- 为博客添加Live图
为博客添加Live图 Apple提供了很生动的Live实况图,在实际展示的过程中非常生动形象,在撰写博客的过程中,我自己也尝试将博客中嵌入实况图片 其实Apple提供的iCloud网页版为我们提供了很 ...