Redis内存淘汰策略?如何处理大Key?

一、Redis 内存淘汰策略

先理解场景:

Redis 是基于内存的,内存不是无限的。

当 Redis 已经达到 maxmemory 限制,再写入新数据时,就需要决定:

是删除一些旧数据,还是直接报错?

这就是 内存淘汰策略

常见淘汰策略

1. noeviction

不淘汰任何数据

如果内存满了,再写入就直接报错。

适合:对数据丢失很敏感的场景。

缺点:可能导致写请求失败。

2. allkeys-lru

所有 key 里,淘汰最近最少使用的数据。

意思是:

谁最近最少被访问,就先删谁。

这个很常见,适合缓存场景。

3. allkeys-lfu

所有 key 里,淘汰最近最不常使用的数据。

和 LRU 不同的是:

  • LRU 看"最近有没有被用过"

  • LFU 看"过去一段时间用得频不频繁"

更适合热点数据比较稳定的场景。

4. volatile-lru

只在 设置了过期时间的 key 中,淘汰最近最少使用的数据。

前提是你的 key 必须设置了 TTL。

5. volatile-lfu

只在 带过期时间的 key 中,淘汰最不常使用的数据。

6. volatile-ttl

只在设置了过期时间的 key 中,优先淘汰剩余生存时间最短的 key。

也就是谁快过期了先删谁。

7. random 系列

比如:

  • allkeys-random

  • volatile-random

随机淘汰,不太常作为首选。

二、什么是大 Key

大 Key 你可以简单理解成:

某一个 Redis key 对应的 value 特别大,或者一个集合里元素特别多。

比如:

  • 一个 String 存了几 MB 甚至几十 MB

  • 一个 List 里几十万条数据

  • 一个 Hash 里几百万 field

  • 一个 Set / ZSet 特别大

大 Key 会带来什么问题

1. 网络阻塞

一次读取或删除大 Key,会传很多数据,网络开销大,响应慢。

2. Redis 阻塞

Redis 是单线程处理命令的。

如果一个命令操作大 Key 时间很长,会阻塞其他请求。

3. 内存不均衡

一个大 Key 可能占很多内存,导致内存分布不合理。

4. 删除代价高

直接 del 一个特别大的 key,可能导致 Redis 卡顿。

5. 主从复制压力大

大 Key 变更时,复制和持久化成本都更高。

三、如何处理大 Key

按"发现 + 拆分 + 删除优化"。

1. 先发现大 Key

可以通过这些方式:

  • redis-cli --bigkeys

  • MEMORY USAGE key

  • SCAN 配合业务排查

  • 监控慢日志、热点 key

意思就是先定位:

到底哪个 key 太大。

2. 拆分大 Key

这是最核心的做法。

比如 String 太大

不要一个 key 存整个大 JSON,

可以按业务字段拆分。

比如 List / Set / Hash 太大

可以做分片拆分:

java 复制代码
user:msg:1
user:msg:2
user:msg:3

或者按时间拆:

java 复制代码
order:202601
order:202602

本质就是:

不要让一个 key 承载太多数据,把它拆成多个小 key。

3. 删除大 Key 时要异步删除

不要直接粗暴 DEL

更推荐:

  • UNLINK

因为它是异步删除,对主线程影响更小。

所以面试里可以说:

对于大 Key 删除,建议使用 UNLINK 替代 DEL,避免阻塞 Redis。

4. 优化数据结构设计

比如:

  • 能分页查询就不要一次性塞全部数据

  • 能落 MySQL / ES 的数据就不要全堆 Redis

  • 只把热点、必要的数据放 Redis

5. 设置合理过期时间

避免无效数据长期堆积,慢慢长成大 Key。

四、面试回答版

Redis 内存淘汰策略 是指当 Redis 达到**maxmemory** 限制后,再写入数据时如何处理。常见策略包括 noeviction,也就是不淘汰直接报错;以及 LRU、LFU、TTL、random 等策略。其中又分为从所有 key 中 淘汰的 allkeys-*和只从设置过期时间 key 中淘汰的 volatile-*。实际缓存场景里,常用的是 allkeys-lruallkeys-lfu
大 Key 指的是单个 key 对应的数据量特别大,比如超大的 String,或者元素特别多的 Hash、List、Set。这会带来网络阻塞、Redis 卡顿、删除慢、主从复制压力大等问题。处理大 Key 的核心思路是先通过 bigkeys 等方式定位 ,再通过业务拆分 把一个大 Key 拆成多个小 Key;如果要删除大 Key ,优先用 UNLINK 异步删除,避免阻塞主线程。

相关推荐
淡泊if2 小时前
eBPF 实战:一次诡异的 Nginx 高延迟,我用 5 分钟在内核里找到了真凶
java·运维·nginx·微服务·ebpf
李白的粉2 小时前
基于springboot的桂林旅游景点导游平台
java·spring boot·毕业设计·课程设计·源代码·桂林旅游景点导游平台
Y001112362 小时前
Day3-MySQL-SQL-2
数据库·sql·mysql
毕设源码-赖学姐2 小时前
【开题答辩全过程】以 花卉交易系统为例,包含答辩的问题和答案
java
weixin_704266052 小时前
Spring整合MyBatis(一)
java·spring·mybatis
翘着二郎腿的程序猿2 小时前
Maven本地化部署与使用全指南
java·maven
历程里程碑2 小时前
Linux 49 HTTP请求与响应实战解析 带http模拟实现源码--万字长文解析
java·开发语言·网络·c++·网络协议·http·排序算法
V1ncent Chen2 小时前
从零学SQL 07 数据过滤
数据库·sql·mysql·数据分析
A10169330712 小时前
maven导入spring框架
数据库·spring·maven