灯下哥谭 灯下哥谭
首页
关于
  • Hermes Agent 平台
  • Claude Code
  • OpenClaw
  • GPU 推理节点运维
  • DeepSeek Harness
  • MySQL 运维知识地图
  • Elasticsearch 运维知识地图
  • Redis 运维知识地图
  • TiDB 体系
  • DBA 常用 SQL 与命令
  • Nginx 运维知识地图
  • Prometheus 监控
  • Docker
  • Systemd
  • Iptables
  • Firewalld
  • Sshd
  • MySQL8 运维 SOP 手册
  • MySQL 实战 45 讲(读书笔记)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

灯下哥谭

灯还亮着
首页
关于
  • Hermes Agent 平台
  • Claude Code
  • OpenClaw
  • GPU 推理节点运维
  • DeepSeek Harness
  • MySQL 运维知识地图
  • Elasticsearch 运维知识地图
  • Redis 运维知识地图
  • TiDB 体系
  • DBA 常用 SQL 与命令
  • Nginx 运维知识地图
  • Prometheus 监控
  • Docker
  • Systemd
  • Iptables
  • Firewalld
  • Sshd
  • MySQL8 运维 SOP 手册
  • MySQL 实战 45 讲(读书笔记)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • MySQL

  • Redis

    • Redis 运维知识地图:从单机到 Cluster 排障
    • Redis 常用查询操作:五种数据类型速查 + 生产环境避坑
    • Redis 集群部署
    • Redis 大 key 分析:三条排查路径怎么选
    • Redis手动进行主从切换
    • Redis集群添加节点之后数据重新均匀分配
    • Redis槽位slot解读
    • Redis Cluster 新增节点 slot 迁移卡住:"open slots" 故障复盘
    • Redis集群的创建、剔除节点与新增节点操作过程
    • Redis配置文件解读
    • redis cluster压测
    • Redis 慢查询告警与抓包分析排障脚本
    • Redis 的可用内存过高时的自动驱逐 key 策略详解
      • 引言
      • Redis 的内存管理机制
      • 驱逐策略详解
        • 1. noeviction
        • 2. allkeys-lru
        • 3. volatile-lru
        • 4. allkeys-random
        • 5. volatile-random
        • 6. volatile-ttl
      • 配置示例
      • 监控与调优
      • 为什么 LRU 是近似的
      • 验证策略生效
        • 1. 确认当前策略
        • 2. 估算合理的 maxmemory
        • 3. 触发驱逐观察
        • 4. 确认淘汰的是冷数据
      • 坑与边界
  • 高性能KV

  • TiDB

  • Elasticsearch

  • 数据管道

  • 其他数据库

  • 数据库
  • Redis
灯下哥谭
2024-06-23
目录

Redis 的可用内存过高时的自动驱逐 key 策略详解原创

# Redis 的可用内存过高时的自动驱逐 key 策略详解

# 引言

Redis 是一个高性能的 key-value 存储,广泛应用于缓存、会话存储等场景。在使用 Redis 时,经常会遇到内存使用过高的问题。为了保证 Redis 的稳定运行,我们需要了解 Redis 如何在内存接近上限时自动驱逐 key 以释放内存。

# Redis 的内存管理机制

Redis 通过配置参数 maxmemory 来设置允许使用的最大内存量。当 Redis 的内存使用量接近 maxmemory 时,它会根据配置的驱逐策略自动删除部分 key 以释放内存。我们可以通过配置参数 maxmemory-policy 来指定驱逐策略。

# 驱逐策略详解

Redis 提供了多种驱逐策略,每种策略适用于不同的应用场景。以下是 Redis 的几种主要驱逐策略:

# 1. noeviction

当内存达到最大限制时,不再执行任何写操作,直接返回错误。适用于希望数据完全保留且可以容忍写入失败的场景。

# 2. allkeys-lru

在所有 key 中,使用 LRU(Least Recently Used)算法驱逐最近最少使用的 key。这是最常用的策略,适用于缓存场景。

# 3. volatile-lru

仅在设置了过期时间的 key 中,使用 LRU 算法驱逐最近最少使用的 key。适用于只希望驱逐设置了过期时间的 key 的场景。

# 4. allkeys-random

在所有 key 中,随机驱逐一些 key。适用于不希望使用 LRU 算法,且可以接受随机驱逐的场景。

# 5. volatile-random

仅在设置了过期时间的 key 中,随机驱逐一些 key。适用于只希望驱逐设置了过期时间的 key 且可以接受随机驱逐的场景。

# 6. volatile-ttl

仅在设置了过期时间的 key 中,优先驱逐剩余生存时间(TTL)最短的 key。适用于希望优先删除即将过期的 key 的场景。

# 配置示例

可以通过修改 Redis 配置文件或运行时使用 CONFIG SET 命令来配置 maxmemory 和 maxmemory-policy。以下是一个配置示例:

# 设置最大内存为 256MB
maxmemory 256mb

# 设置驱逐策略为 allkeys-lru
maxmemory-p<PASSWORD> allkeys-lru
1
2
3
4
5

或者在运行时设置:

CONFIG SET maxmemory 256mb
CONFIG SET maxmemory-p<PASSWORD> allkeys-lru
1
2

# 监控与调优

为了更好地管理 Redis 的内存使用,可以结合 Redis 提供的监控工具,如 INFO memory 命令,监控内存使用情况。同时,可以根据实际应用需求和内存使用情况,动态调整 maxmemory 和驱逐策略。


# 为什么 LRU 是近似的

Redis 的 allkeys-lru 和 volatile-lru 采用近似 LRU 算法,而非严格 LRU:

严格 LRU 的问题:

  • 需要为每个 key 维护访问时间戳,并在淘汰时遍历所有 key 找出最久未使用的
  • 时间复杂度 O(N),对单线程 Redis 来说成本太高

近似 LRU 的实现(Redis 3.0+):

  • 维护一个候选池(默认 5 个 key)
  • 每次需要淘汰时,随机采样 N 个 key(maxmemory-samples,默认 5),放入候选池
  • 淘汰候选池中最久未使用的 key

与严格 LRU 的差异:

  • 采样数量越大,近似度越高,但 CPU 开销也越大
  • 默认 5 个样本,Redis 官方测试显示近似度接近 90%
  • 如果业务对 LRU 准确性要求极高,可以调大 maxmemory-samples(如 10)

配置建议:

CONFIG SET maxmemory-samples 10  # 提高近似 LRU 精度,增加一点 CPU 开销
1

# 验证策略生效

# 1. 确认当前策略

redis-cli CONFIG GET maxmemory-p<PASSWORD>
redis-cli CONFIG GET maxmemory
1
2

# 2. 估算合理的 maxmemory

# 查看当前内存使用
redis-cli INFO memory | grep used_memory_human

# 查看 key 数量
redis-cli DBSIZE

# 估算每个 key 平均大小(字节)
# 粗略公式:used_memory / keyspace_hits(或 DBSIZE)
1
2
3
4
5
6
7
8

设置原则:

  • 单机部署:maxmemory 设为物理内存的 60%-70%,留出 fork 重写时的缓冲
  • 容器部署:设为容器 limit 的 80% 左右

# 3. 触发驱逐观察

# 临时把 maxmemory 设低,强制触发驱逐
redis-cli CONFIG SET maxmemory 10485760  # 10MB

# 写入大量数据触发驱逐
redis-cli debug populate 100000 test 1000

# 观察驱逐统计
redis-cli INFO stats | grep evicted_keys
1
2
3
4
5
6
7
8

看到 evicted_keys 增加,说明驱逐策略正在工作。

# 4. 确认淘汰的是冷数据

# 观察命中率变化
redis-cli INFO stats | grep keyspace_hit_ratio
1
2

如果驱逐后命中率大幅下降,说明可能误删了热 key,需要调整策略或增加内存。


# 坑与边界

  1. allkeys-lru 误删热 key:刚被访问的 key 如果在采样时没被抽中,仍可能被误判为「冷」而删除。对「绝对不能丢」的热数据,应设置过期时间并改用 volatile-lru,或直接不设 maxmemory(用 noeviction)。

  2. volatile- 在无过期时间 key 上的回退行为*:如果所有 key 都没设过期时间,volatile-lru、volatile-random、volatile-ttl 的效果等同于 noeviction(拒绝写入)。这可能让应用以为 Redis 挂了。

  3. 驱逐与持久化的并发问题:AOF 重写(BGREWRITEAOF)或 RDB 快照(BGSAVE)需要 fork() 子进程,内存会瞬间翻倍。如果 maxmemory 设置过满,fork 可能失败或触发 OOM。建议 maxmemory 至少预留 30% 缓冲。

  4. LFU 的计数器溢出:3.0+ 新增 allkeys-lfu/volatile-lfu,用访问频率而非时间判断。但计数器会随时间衰减,极端场景下高频 key 也可能被误判。

  5. 大 key 的驱逐开销:一个 100MB 的 key 被淘汰时,删除操作会阻塞主线程。如果大量使用 allkeys-random,可能随机到大 key 导致延迟尖刺。

  6. noeviction 不是免费的:当内存打满后,每次写入都会返回错误,应用层需要处理异常。如果未妥善处理,可能导致业务逻辑中断而非简单的缓存失效。

#容量规划#Redis
上次更新: 9/11/2026

← Redis 慢查询告警与抓包分析排障脚本 KeyDB 深度解析:多线程 Redis 分支的核心机制与选型权衡→

最近更新
01
DeepSeek Harness 实战 06|学习笔记:插件、工具、技能不在同一个维度上 原创
09-11
02
DeepSeek Harness 实战 05|让两个编码 Agent 共用一份长期记忆 原创
09-09
03
DeepSeek Harness 实战 04|学习笔记:从「已知限制」里读出三处设计张力 原创
09-08
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式