Redis内存淘汰策略
Redis 的五种数据结构各有特色,用对了才能发挥它的优势。很多人只用到了 String 和 Hash,却不知道 List、Set、ZSet 在特定场景下更合适。本文从应用场景出发,讲什么时候用什么类型。
一、内存管理基础
#
1.1 查看内存使用
# 查看内存信息 |
#
1.2 配置最大内存
# redis.conf |
#
1.3 内存达到上限的行为
当 used_memory > maxmemory 时: |
二、淘汰策略详解
#
2.1 策略分类
| 策略 | 说明 | 范围 |
|---|---|---|
| noeviction | 不淘汰,返回错误 | 所有 |
| allkeys-lru | 淘汰最近最少使用的key | 所有key |
| allkeys-lfu | 淘汰使用频率最低的key | 所有key |
| allkeys-random | 随机淘汰key | 所有key |
| volatile-lru | 淘汰设置了过期时间的key中最近最少使用的 | 有过期时间的 |
| volatile-lfu | 淘汰设置了过期时间的key中使用频率最低的 | 有过期时间的 |
| volatile-random | 随机淘汰设置了过期时间的key | 有过期时间的 |
| volatile-ttl | 淘汰快要过期的key | 有过期时间的 |
#
2.2 LRU策略
LRU(Least Recently Used):最近最少使用
Redis的近似LRU实现: |
配置:
maxmemory-policy allkeys-lru |
#
2.3 LFU策略
LFU(Least Frequently Used):最少使用频率
Redis 4.0+ 引入的LFU实现: |
配置:
maxmemory-policy allkeys-lfu |
LFU vs LRU:
| 特性 | LRU | LFU |
|---|---|---|
| 关注点 | 最近访问时间 | 访问频率 |
| 适合场景 | 热点数据变化快 | 有明确的热度差异 |
| 新数据 | 容易淘汰 | 需要时间积累计数 |
| 突发流量 | 可能淘汰热点 | 更稳定 |
#
2.4 TTL策略
volatile-ttl:优先淘汰即将过期的key
适用场景: |
#
2.5 Random策略
allkeys-random / volatile-random:随机淘汰
适用场景: |
三、策略选择指南
#
3.1 选择决策树
是否需要淘汰数据? |
#
3.2 场景推荐
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 纯缓存 | allkeys-lru | 缓存所有数据,LRU最自然 |
| 持久化+缓存混合 | volatile-lru | 保护未设置过期的数据 |
| 有明显热点 | allkeys-lfu | 保留高频访问数据 |
| 数据均匀访问 | allkeys-random | 简单高效 |
| 缓存都有TTL | volatile-ttl | 让快过期的先淘汰 |
| 不允许丢数据 | noeviction | 内存满时返回错误 |
#
3.3 生产配置示例
# 场景1:纯缓存(电商商品) |
四、内存优化
#
4.1 数据结构优化
# 1. 使用Hash存储对象(比String序列化省空间) |
#
4.2 数据压缩
# 开启RDB压缩 |
#
4.3 监控内存使用
# 查看内存使用详情 |
#
4.4 内存分析工具
# redis-rdb-tools: 分析RDB文件内存使用 |
五、常见问题
#
5.1 内存突增导致OOM
# 现象:used_memory突然达到maxmemory,写操作失败 |
#
5.2 淘汰策略不生效
# 检查配置 |
#
5.3 内存碎片率高
# 查看碎片率 |
六、总结
| 策略 | 淘汰范围 | 算法复杂度 | 适用场景 |
|---|---|---|---|
| allkeys-lru | 所有key | O(N)采样 | 通用缓存 |
| allkeys-lfu | 所有key | O(N)采样 | 热点数据 |
| allkeys-random | 所有key | O(1) | 均匀访问 |
| volatile-lru | 有过期时间的 | O(N)采样 | 混合存储 |
| volatile-lfu | 有过期时间的 | O(N)采样 | 热点+过期 |
| volatile-ttl | 有过期时间的 | O(N)排序 | TTL优化 |
| volatile-random | 有过期时间的 | O(1) | 简单场景 |
| noeviction | 不淘汰 | - | 不允许丢数据 |
内存管理的核心原则:
- 设置合理的maxmemory:不超过物理内存的75%
- 选择合适的淘汰策略:根据业务特点选择LRU/LFU/Random
- 监控内存使用:及时发现内存异常
- 优化数据结构:使用ziplist等紧凑编码
- 定期分析大key:避免单个key占用过多内存
核心要点
String:简单的键值对,适合缓存、计数器
Hash:存储对象属性,适合用户信息、配置
List:有序列表,适合消息队列、最新列表
Set:无序去重,适合共同好友、抽奖
ZSet:有序集合,适合排行榜、积分系统
总结
选择合适的数据结构是使用 Redis 的关键。在实际项目中,根据业务需求选择合适的类型,可以提升性能和开发效率。