Redis 内存淘汰策略深度解析(最新推荐)

2025-03-10 17:50

本文主要是介绍Redis 内存淘汰策略深度解析(最新推荐),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand...

Redis 作为高性能的内存数据库,其内存资源的高效管理直接关系到系统的稳定性yorckf和性能。当 Redis 的内存使用达到配置的最大值(maxmemory)时,新的写入操作将触发内存淘汰机制(Eviction Policy),以释放空间存储新数据。本文将深入探讨 Redis 的内存淘汰策略、实现原理、适用场景及最佳实践。

一、 内存淘汰策略概述

Redis 的内存淘汰策略决定了在内存不足时,如何选择需要删除的键来释放空间。这些策略可以分为两大类:

  • 基于过期时间的淘汰​(volatile-*):仅针对设置了过期时间的键。
  • 全局淘汰​(allkeys-*):针对所有键,无论是否设置过期时间。

Redis 支持以下 8 种内存淘汰策略

noeviction:默认策略,禁止写入新数据,直接返回错误。
volatile-lru:淘汰最近最少使用(LRU)的设置了过期时间的键。
volatile-lfu:淘汰最不经常使用(LFU)的设置了过期时间的键。
volatile-random:随机淘汰设置了过期时间的键。
volatile-ttl:优先淘汰剩余生存时间(TTL)最短的键。
allkeys-lru:淘汰所有键中最近最少使用的键。
allkeys-lfu:淘汰所有键中最不经常使用的键。
allkeys-random:随机淘汰任意键。

二、内存淘汰策略详解

2.1 ​noeviction(不淘汰)​

​行为:当内存不足时,拒绝所有写入命令(如 SET、LPUSH),但允许读取操作。
​适用场景:适用于数据不可丢失的场景(如持久化存储),需确保内存足够或配合持久化机制。
缺点:若内存不足且无持久化,可能导致服务不可用。

2.2 ​LRU(Least Recently Used)​

​原理:淘汰最近最久未被访问的键。
​Redis 实现:Redis 使用近似 LRU 算法,通过随机采样(默认取 5 个键)选择最久未使用的键,而非遍历所有键,以减少计算开销。
​适用场景:适用于缓存场景,优先保留热点数据。
​命令示例

CONFIG SET maxmemory-policy volatile-lru  # 针对带过期时间的键
CONFIG SET maxmemory-policy allkeys-lru   # 针对所有键

2.3 ​LFU(Least Frequently Used)​

​原理:淘汰访php问频率最低的键(Redis 4.0 引入)。
​Redis 实现:通过计数器统计键的访问频率,并随时间衰减历史计数,避免长期累积导致无法淘汰旧键。
​适用场景:适合长期缓存,如高频访问的静态数据。
​命令示例

CONFIG SET maxmemory-policy volatile-lfu  # 针对带过期时间的键
CONFIG SET maxmemory-policy allkeys-lfu   # 针对所有键

2.4 ​TTL(Time To Live)​

​原理:优先淘汰剩余生存时间(TTL)最短的键。
​适用场景:适用于明确知道键生命周期的场景(如临时会话数据)。
限制:仅对设置了过期时间的键生效。
​命令示例

CONFIG SET maxmemory-policy volatile-ttl

2.5 ​Random(随机淘汰)​

​原理:随机选择键进行淘汰。
​适用场景:内存压力大且数据重要性均等时,快速释放内存。
​命令示例

CONFIG SET maxmemory-policy volatile-random  # 针对带过期时间的键
CONFIG SET maxmemory-policy allkeys-random   # 针对所有键

三、 内存淘汰的底层实现

3.1 ​LRU/LFU 的近似算法

  • Redis 通过 ​evictionPoolEntry​结构维护候选淘汰键池。每次淘汰时,随机采样一组键,更新其访问时间或频率信息,选择最不活跃的键删除。
  • ​LRU 时钟:Redis 使用全局 24 位时钟(精度为秒)记录键的最近访问时间。内存中每个对象存储与全局时钟的差值(lru字段),而非精确时间戳。
  • ​LFU 计数器:每个键的 lru 字段被拆分为两部分:
    • 高 16 位:最近访问时间的分钟级精度。
    • 低 8 位:访问频率计数器(0~255),通过概率递增,随时间衰减。

3.2 ​淘汰流程

  • 客户端执行写入命令触发内存检查。
  • Redis 检查 maxmemory 是否已超出。
  • 根据配置的策略选择待淘汰键。
  • 删除键并触发相javascript关事件(如 evicted 通知)。

四、 如何选择合适的内存淘汰策略?

4.1 ​缓存场景

http://www.chinasem.cn推荐策略:allkeys-lru 或 allkeys-lfu
​理由:优先保留热点数据,最大化缓存命中率。

4.2 ​持久化存储

​推荐策略:noeviction(需确保内存足够或启用持久化)。
​替代方案:若允许部分数据丢失,可使用 volatile-lru 结合过期时间。

4.3 ​临时数据场景

​推荐策略:volatile-ttl
​理由:自动清理生命周期明确的数据(如验证码、会话信息)。

4.4 ​混合型数据

​推荐策略:allkeys-lru + 部分键设置过期时间。
​示例:电商系统中,商品详情用 allkeys-lru 缓存,购物车数据设置 TTL。

五、最佳实践与注意事项

5.1 ​配置建议

​设置合理的 maxmemory:通常为物理内存的 80%~90%,避免 OOM。
​监控内存使用:

INFO memory  # 查看内存指标(used_memory、maxmemory)
INFO stats    # 查看 evicted_keys(淘汰键数量)

5.2 ​避免大规模淘汰

​分片设计:通过集群分散数据,减少单个节点的内存压力。
​预热缓存:重启后预加载高频数据,避免冷启动时集中淘汰。

5.3 ​常见误区

volatile-ttl 不依赖惰性删除:该策略仅在内存不足时触发,仍需依赖定期/惰性删除清理过期键。
​LFU 计数器并非精确值:访问频率通过概率递增,适用于相对比较而非绝对计数。

六、总结

Redis 的内存淘汰策略是平衡内存使用与性能的关键机制。理解不同策略的原理和适用场景,结合业务需求合理配置,可显著提升系统的稳定性和效率。在高并发场景下,建议通过监控工具(如 RedisInsight、Prometheus)实时跟踪内存和淘汰指标,动态调整策略和资源配置。

通过本文的深度解析,希望您能掌握 Redis 内存淘汰的核心机制,并在实践中灵活运用,构建高效可靠的 Redis 服务。

参考资料

Redis 官方文档:https://redis.io/docs/reference/eviction/
《Redis 设计与实现》——黄健宏
Redis 源码解析(evict.c、object.c)

到此这篇关于Redis 内存淘汰策略深度解析的文章就介绍到这了,更多相关Redis 内存淘汰策略内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于Redis 内存淘汰策略深度解析(最新推荐)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153681

相关文章

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

一文解析C#中的StringSplitOptions枚举

《一文解析C#中的StringSplitOptions枚举》StringSplitOptions是C#中的一个枚举类型,用于控制string.Split()方法分割字符串时的行为,核心作用是处理分割后... 目录C#的StringSplitOptions枚举1.StringSplitOptions枚举的常用

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

Redis 基本数据类型和使用详解

《Redis基本数据类型和使用详解》String是Redis最基本的数据类型,一个键对应一个值,它的功能十分强大,可以存储字符串、整数、浮点数等多种数据格式,本文给大家介绍Redis基本数据类型和... 目录一、Redis 入门介绍二、Redis 的五大基本数据类型2.1 String 类型2.2 Hash

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三

Redis中Set结构使用过程与原理说明

《Redis中Set结构使用过程与原理说明》本文解析了RedisSet数据结构,涵盖其基本操作(如添加、查找)、集合运算(交并差)、底层实现(intset与hashtable自动切换机制)、典型应用场... 目录开篇:从购物车到Redis Set一、Redis Set的基本操作1.1 编程常用命令1.2 集

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse