深色模式
Redis 内存与淘汰策略
摘要:Redis 内存写满后会按
maxmemory-policy淘汰 key 或直接拒绝写入。本文配置内存上限与淘汰策略,用内置命令找出大 key,并给出内存异常上涨的排查路径。
适用环境
bash
redis-cli -a '密码' INFO memory | grep -E 'used_memory_human|maxmemory_human|maxmemory_policy|mem_fragmentation_ratio'
redis-cli -a '密码' CONFIG GET maxmemory1
2
2
操作步骤
1. 设置内存上限
bash
# 在线设置(重启失效)
redis-cli -a '密码' CONFIG SET maxmemory 4gb
# 持久化到配置文件
redis-cli -a '密码' CONFIG REWRITE1
2
3
4
2
3
4
ini
maxmemory 4gb # 建议不超过物理内存的 60%~70%,留出 fork 与系统余量1
2. 选择淘汰策略
| 策略 | 含义 | 适用 |
|---|---|---|
noeviction | 不淘汰,写请求报错 | 数据不可丢、需人工介入 |
allkeys-lru | 全体 key 按最近最少使用淘汰 | 纯缓存场景首选 |
volatile-lru | 只在设了过期时间的 key 中 LRU 淘汰 | 缓存与持久数据混布 |
allkeys-lfu | 全体按访问频率淘汰 | 有明显热点且希望保留高频 key |
volatile-ttl | 优先淘汰剩余寿命短的 | 按 TTL 层次明确的场景 |
bash
redis-cli -a '密码' CONFIG SET maxmemory-policy allkeys-lru1
危险
把 Redis 当持久化存储却配置 allkeys-lru,会在内存满时静默丢数据。持久数据要么不设淘汰策略并做容量监控,要么放在独立实例上与缓存隔离。
3. 找出占用大户
bash
redis-cli -a '密码' --bigkeys # 扫描各类结构中最大的 key
redis-cli -a '密码' MEMORY USAGE user:1001 # 单个 key 占用字节数
redis-cli -a '密码' --memkeys # 按内存排序(Redis 7+,--memkeys-samples)1
2
3
2
3
bash
# 统计某前缀 key 数量,判断是否有无限增长
redis-cli -a '密码' --scan --pattern 'session:*' | wc -l1
2
2
4. 处理内存碎片
bash
redis-cli -a '密码' INFO memory | grep mem_fragmentation_ratio
# 比率 > 1.5 说明碎片较多;< 1 说明使用了 swap,性能会很差
redis-cli -a '密码' MEMORY PURGE # Redis 4+,主动归还内存(需 jemalloc)1
2
3
2
3
5. 设置过期时间,避免只增不减
bash
redis-cli -a '密码' SET cache:page:1 '<html>' EX 3600 # 写时就带上 TTL
redis-cli -a '密码' EXPIRE old:key 86400
redis-cli -a '密码' TTL old:key1
2
3
2
3
验证
bash
redis-cli -a '密码' INFO memory | grep -E 'used_memory_human|maxmemory_human|maxmemory_policy'
# 写入压力测试后观察是否出现 evicted_keys 增长
redis-cli -a '密码' INFO stats | grep evicted_keys
# 验证淘汰行为(在测试实例上)
redis-cli -a '密码' CONFIG SET maxmemory 10mb
redis-cli -a '密码' DEBUG POPULATE 100000 k 100
redis-cli -a '密码' INFO stats | grep evicted_keys # 应大于 01
2
3
4
5
6
7
8
2
3
4
5
6
7
8
常见坑
WARNING
maxmemory 0(默认)表示不限制,在容器里会直接触发 OOM Kill;容器化部署必须显式设置并小于容器 limit。
WARNING
INFO memory 的 used_memory 不含复制缓冲区与客户端输出缓冲;主库内存看似不高却被 OOM,通常是大量从库同步或慢客户端堆积输出缓冲导致。
DANGER
DEBUG POPULATE、FLUSHALL 等命令仅可用于测试实例;对生产实例执行会瞬间打满内存或清空数据。