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-randomvolatile-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 --bigkeysMEMORY USAGE keySCAN配合业务排查监控慢日志、热点 key意思就是先定位到底哪个 key 太大。2. 拆分大 Key这是最核心的做法。比如 String 太大不要一个 key 存整个大 JSON可以按业务字段拆分。比如 List / Set / Hash 太大可以做分片拆分user:msg:1 user:msg:2 user:msg:3或者按时间拆order:202601 order:202602本质就是不要让一个 key 承载太多数据把它拆成多个小 key。3. 删除大 Key 时要异步删除不要直接粗暴DEL。更推荐UNLINK因为它是异步删除对主线程影响更小。所以面试里可以说对于大 Key 删除建议使用UNLINK替代DEL避免阻塞 Redis。4. 优化数据结构设计比如能分页查询就不要一次性塞全部数据能落 MySQL / ES 的数据就不要全堆 Redis只把热点、必要的数据放 Redis5. 设置合理过期时间避免无效数据长期堆积慢慢长成大 Key。四、面试回答版Redis内存淘汰策略是指当 Redis 达到maxmemory限制后再写入数据时如何处理。常见策略包括noeviction也就是不淘汰直接报错以及 LRU、LFU、TTL、random 等策略。其中又分为从所有 key 中淘汰的allkeys-*和只从设置过期时间 key中淘汰的volatile-*。实际缓存场景里常用的是allkeys-lru或allkeys-lfu。大 Key指的是单个 key 对应的数据量特别大比如超大的 String或者元素特别多的 Hash、List、Set。这会带来网络阻塞、Redis 卡顿、删除慢、主从复制压力大等问题。处理大 Key 的核心思路是先通过bigkeys等方式定位再通过业务拆分把一个大 Key 拆成多个小 Key如果要删除大 Key优先用UNLINK异步删除避免阻塞主线程。