大数据-47 Redis 内存控制、Key 过期与数据淘汰策略详解

点一下关注吧!!!非常感谢!!持续更新!!!

🚀 AI篇持续更新中!(长期更新)

AI炼丹日志-30-新发布【1T 万亿】参数量大模型!Kimi‑K2开源大模型解读与实践,持续打造实用AI工具指南!📐🤖

💻 Java篇正式开启!(300篇)

目前2025年07月21日更新到: Java-77 深入浅出 RPC Dubbo 负载均衡全解析:策略、配置与自定义实现实战 MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务正在更新!深入浅出助你打牢基础!

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈! 大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

Redis在理想环境下具备极高读写性能,但在实际应用中受网络、数据结构复杂度等影响。内存使用是Redis运维的核心挑战,Key数量持续增长可能导致内存耗尽。Redis提供多种内存淘汰策略,如allkeys-lru、volatile-ttl等,适配不同业务需求。通过合理配置maxmemory与淘汰策略,可保障系统稳定运行。键过期机制(如EXPIRE、TTL、EXPIREAT)适用于缓存、临时数据、分布式锁等场景。此外,Redis采用惰性删除与主动删除机制管理内存。选择合适策略、设置合理TTL、加强监控与容量规划,是优化Redis性能与可靠性的关键。

章节内容

上一节我们完成了:

  • RDB的配置方式、触发方式
  • RDB的文件结构、优点、缺点
  • AOF的配置方式、触发方式
  • AOF的优点、缺点、瘦身方式
  • RDB + AOF 混合方式

Redis性能分析及内存管理策略

Redis性能基准

根据官方基准测试数据,Redis在理想环境下表现出卓越的性能:

  • 读取性能 :每秒可处理约110,000次读操作
    • 实际环境中,性能受网络延迟、数据结构复杂度等因素影响
    • 例如:简单的字符串键读取比复杂的有序集合操作更快
  • 写入性能 :每秒可处理约81,000次写操作
    • 写入性能通常低于读取性能
    • AOF持久化开启时会进一步影响写入吞吐量

内存管理挑战

随着长期使用,Redis会面临以下内存问题:

  • Key数量增长:应用持续运行导致存储的Key数量不断增加
  • 内存耗尽风险 :当物理内存被占满时,Redis可能出现以下情况:
    • 写入操作失败(如果配置为noeviction策略)
    • 系统开始使用交换空间(SWAP),导致性能急剧下降
    • 可能触发OOM(Out Of Memory)错误

过期淘汰策略解决方案

为避免内存耗尽,Redis提供了多种内存淘汰策略:

  1. volatile-lru

    • 从设置了过期时间的Key中淘汰最近最少使用的
    • 适用于缓存场景,优先保留热点数据
  2. allkeys-lru

    • 从所有Key中淘汰最近最少使用的
    • 适合将Redis同时用作缓存和持久存储的场景
  3. volatile-ttl

    • 从设置了过期时间的Key中淘汰剩余生存时间(TTL)最短的
    • 优先移除即将过期的数据
  4. volatile-random

    • 从设置了过期时间的Key中随机淘汰
    • 开销最小但不够精准
  5. allkeys-random

    • 从所有Key中随机淘汰
    • 适用于数据重要性相当的情况
  6. noeviction

    • 不淘汰任何Key,在内存不足时返回错误
    • 适合数据绝对不能丢失的场景

实际应用建议

  • 缓存场景 :推荐volatile-lruallkeys-lru策略,配合合理的TTL设置
  • 混合使用 :如果Redis同时用于缓存和持久化存储,考虑allkeys-lru
  • 监控 :定期检查used_memoryevicted_keys指标
  • 容量规划:根据业务增长预估内存需求,提前扩容

通过合理配置淘汰策略,可以在保证性能的同时有效管理内存使用。

MaxMemory

不设置maxmemory的情况

适用场景

  1. Key数量固定:当Redis中存储的Key数量是预先确定的,不会随时间增长时。

    • 例如:系统配置缓存、静态字典表等场景
    • 这种情况下可以精确计算所需内存,无需淘汰机制
  2. 作为主数据库:当Redis承担主要数据存储职责时

    • 需要保证数据的完整性,不允许数据丢失
    • 常见于需要持久化存储的业务场景
  3. 集群扩展:可以通过增加Redis节点来扩展容量

    • 水平扩展方案:使用Redis Cluster或客户端分片
    • 垂直扩展方案:升级服务器内存配置

淘汰策略的默认行为

  • 默认设置noeviction(禁止驱逐)
  • 当内存不足时的行为:
    1. 新写入操作会返回错误(如SET命令返回OOM错误)
    2. 所有读操作可以正常执行
    3. 不会自动删除任何已有数据

运维建议

  • 在这种配置下,建议:
    1. 密切监控内存使用情况
    2. 提前规划容量扩展方案
    3. 设置适当的告警阈值

设置的情况

Redis 作为缓存使用,不断地增加Key,MaxMemory默认是0不进行限制。 在服务器上,保留1G给操作系统,剩下的就可以用作Redis的缓存。

通过修改 redis.conf 可以配置这个值:

shell 复制代码
maxmemory 1024mb
# 获取值
CONFIG GET maxmemory

设置MaxMemory后,当趋近于设置的值时,通过缓存的淘汰策略,就会从内存中删除

Redis 键过期机制详解

EXPIRE 命令的基本用法

EXPIRE 是 Redis 中最常用的设置键过期时间的方式。该命令允许你为一个已存在的键设置存活时间(TTL,Time To Live),当这个时间到期后,Redis 会自动删除该键。

基本语法

redis 复制代码
EXPIRE key seconds
  • key: 需要设置过期时间的键名
  • seconds: 过期时间,以秒为单位

实际应用示例

  1. 设置键的过期时间
shell 复制代码
./redis-cli
# 设置键"name"在2秒后过期
expire name 2 
# 立即查询该键,可以获取到值
get name
# 等待2秒后再查询,返回nil
get name
  1. 永久有效的键
shell 复制代码
set name 123
# 查看键的剩余生存时间,返回-1表示永久有效
ttl name
  1. 修改已有键的过期时间
shell 复制代码
# 为已存在的键设置10秒过期时间
expire name 10
# 查看剩余生存时间,返回剩余秒数
ttl name

其他相关命令

  1. PEXPIRE:以毫秒为单位设置过期时间
redis 复制代码
PEXPIRE key milliseconds
  1. EXPIREAT:设置键在指定的UNIX时间戳过期
redis 复制代码
EXPIREAT key timestamp
  1. TTL:查看键的剩余生存时间(秒)
redis 复制代码
TTL key
  1. PTTL:查看键的剩余生存时间(毫秒)
redis 复制代码
PTTL key

使用场景

  1. 临时数据存储:如验证码、会话token等需要自动清理的数据

    • 验证码场景:短信/邮件验证码通常在5-10分钟后失效
    • 会话管理:用户登录token设置30天有效期
    • 临时文件存储:上传的临时文件24小时后自动删除
    • 示例:SET verification_code "123456" EX 300 设置5分钟有效期
  2. 缓存控制:设置缓存数据的自动失效时间

    • 数据库查询结果缓存:设置10分钟TTL防止缓存雪崩
    • 热点数据缓存:电商商品信息设置1小时自动刷新
    • 多级缓存协调:本地缓存与Redis缓存过期时间同步
    • 实现方式:SET product:1001 "{...}" EX 3600
  3. 限时活动:活动数据的自动下架

    • 秒杀活动:设置活动精确的结束时间
    • 优惠券发放:限定使用有效期
    • 新用户福利:注册后7天内有效
    • 示例:电商双11活动SET activity:double11 "started" EXAT 1636639200
  4. 分布式锁:设置锁的自动释放时间防止死锁

    • 临界资源保护:设置合理的锁持有时间
    • 自动续期机制:配合看门狗线程实现锁续期
    • 故障恢复:确保服务崩溃后锁能自动释放
    • 实现方案:SET lock:order 1 NX EX 30 获取30秒有效期的锁
  5. 补充应用场景

    • 消息队列:延迟消息的定时投递
    • 频率限制:API调用次数限制的自动重置
    • 临时配置:特殊时期的业务规则配置
    • 设备状态:物联网设备在线状态的超时检测

注意事项

  1. 过期时间精度:Redis的过期删除不是实时的,而是采用惰性删除和定期删除相结合的方式
  2. 持久化影响:RDB和AOF持久化方式会影响过期键的处理
  3. 复制环境下:主从节点的过期处理机制有所不同
  4. 对于已设置过期时间的键,再次执行EXPIRE会覆盖之前的设置

删除策略

Redis 数据的删除有定时删除惰性删除主动删除 三种方式。' Redis 目前采用的是:

  • 惰性删除
  • 主动删除

定时删除

在设置键的过期时间时,创建一个定时器,让定时器在指定时间时删除键。

惰性删除

在 key 被访问的时候发现过期了,就删除这条数据。

主动删除

我们打开 redis.conf 可以配置主动删除的策略:

shell 复制代码
# 默认是 no-enviction 不删除
maxmemory-policy allkeys-lru

主动删除: LRU

LRU(Least Recently Used)最近最少使用,算法根据数据的历史访问记录来进行淘汰数据。 其核心思想是:如果数据最近被访问过,那么将来被访问的概率也会更高

最常见的实现是使用一个链表来保存数据:

  • 新数据插入到链表头部
  • 每当缓存命中的时候,则将数据移动到链表的头部
  • 链表满了的时候,将链表尾部数据删除
  • 在Java中可以使用LinkedHashMap来实现LRU

Redis-LRU

在服务器中保存了 LRU 计数器:server.lrulock,会定时更新,这个值是根据 server.unixtime 来计算的。 LRU的数据淘汰机制是:在数据集中随机挑选几个值,取出其中LRU最大的淘汰掉。

  • volatile-lru:从设置过期时间的数据集中挑选最少使用的淘汰
  • allkeys-lru:从数据集中挑选最近最少使用的数据淘汰

LFU

LFU(Least Frequency used)最不经常使用,如果一个数据在最近一段时间内使用次数很少,那么将来一段时间内被使用的可能性也很小。

  • volatile-lfu 同LRU
  • allkeys-lfu 同LRU
  • volatile-random 从设置过期时间的数据集中随机淘汰数据
  • allkeys-random 从数据集中任意选择进行淘汰

TTL

  • volatile-ttl 从设置过期时间的数据里,选择快要过期的数据淘汰

noenviction

禁止驱逐数据,不淘汰数据(默认的)

Redis淘汰策略选择指南

常用淘汰策略详解

  1. allkeys-lru(全库LRU淘汰)

    • 适用场景:当你不确定哪种淘汰策略最合适时,这是最安全的默认选择
    • 工作原理:基于最近最少使用(LRU)算法淘汰所有键空间中的键
    • 优势:有效实现冷热数据交换,将最不常用的数据优先淘汰
    • 示例:一个电商网站的商品缓存,热门商品会保持活跃,而冷门商品会被自动淘汰
  2. volatile-lru(仅过期键LRU淘汰)

    • 性能说明 :相比allkeys-lru性能较差,因为需要额外检查键的过期时间
    • 工作流程
      1. 首先检查键是否设置了过期时间
      2. 然后在这些设置了过期时间的键中应用LRU算法
    • 适用场景:当你有明确区分长期数据和临时数据的业务需求时
  3. allkeys-random(全库随机淘汰)

    • 设计目的:当请求符合平均分布,即每个键被访问概率相当时最有效
    • 使用示例:缓存大量一次性使用的临时数据,且这些数据的重要性没有明显差异
    • 注意事项:可能导致重要数据被意外淘汰,不适合有明显热点数据的场景
  4. volatile-ttl(剩余存活时间淘汰)

    • 高级控制:允许开发者通过精确设置TTL来自主控制淘汰顺序
    • 实现方式:优先淘汰剩余生存时间(TTL)最短的键
    • 典型应用
      • 临时会话数据管理
      • 限时优惠活动数据缓存
      • 需要精确控制缓存生命周期的场景

策略选择建议

  • 内存不足时的默认选择 :优先考虑allkeys-lru
  • 有明显冷热数据区分allkeys-lru是最佳选择
  • 数据重要性均匀分布 :可尝试allkeys-random
  • 需要精确控制淘汰顺序 :使用volatile-ttl并合理设置过期时间
  • 混合型数据 :可以将持久数据和临时数据分开存储,对临时数据部分使用volatile-lru
相关推荐
源代码•宸5 分钟前
Leetcode—712. 两个字符串的最小ASCII删除和【中等】
开发语言·后端·算法·leetcode·职场和发展·golang·dp
知识分享小能手13 分钟前
Ubuntu入门学习教程,从入门到精通,Ubuntu 22.04 中的大数据 —— 知识点详解 (24)
大数据·学习·ubuntu
何中应14 分钟前
关于查询方式的总结与讨论
后端·缓存·查询
Victor35618 分钟前
Hibernate(36)Hibernate如何处理多对多关系?
后端
Victor35620 分钟前
Hibernate(35)什么是Hibernate的聚合函数?
后端
城数派24 分钟前
2019-2025年各区县逐月新房房价数据(Excel/Shp格式)
大数据·数据分析·excel
进阶的小名25 分钟前
[超轻量级消息队列(MQ)] Redis 不只是缓存:我用 Redis Stream 实现了一个 MQ(自定义注解方式)
数据库·spring boot·redis·缓存·消息队列·个人开发
专注数据的痴汉29 分钟前
「数据获取」中国会计年鉴(1996-2024)
大数据·人工智能·信息可视化
何中应30 分钟前
@Autowrited和@Resource注解的区别及使用场景
java·开发语言·spring boot·后端·spring
源代码•宸31 分钟前
Golang语法进阶(Context)
开发语言·后端·算法·golang·context·withvalue·withcancel