[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f1b300lqgtfmoj":3,"$f250wz8h39yydc":8,"$f2mmjxrvf7hurr":29,"$f1ypo34fz8wxll":33,"$f1po9zlxd16vat":44,"toc--1046845214-5-5":48},{"description":4,"domain":5,"id":6,"keywords":4,"title":7},"","api.kongjs.com",1,"默认",[9,20,24],{"children":10,"icon":4,"id":11,"linkType":12,"linkUrl":13,"parentId":14,"sort":15,"status":16,"target":17,"title":18,"visible":19},null,"447369447469600768","URL","\u002F","0",0,"1","_self","首页",true,{"children":10,"icon":4,"id":21,"linkType":12,"linkUrl":22,"parentId":14,"sort":15,"status":16,"target":17,"title":23,"visible":19},"447369693859794944","\u002Fnotes","笔记",{"children":10,"icon":4,"id":25,"linkType":26,"linkUrl":27,"parentId":14,"sort":15,"status":16,"target":17,"title":28,"visible":19},"447369977960976384","PAGE","\u002Fabout","关于我",{"category":10,"categoryId":10,"cover":10,"description":4,"fileId":10,"id":30,"publishAt":10,"tags":31,"title":32},"453168730659102720",[],"Redis面试核心知识",[34,37,40],{"children":10,"description":4,"id":35,"noteId":30,"parentId":14,"sort":15,"status":16,"title":36},"453168855791968256","Redis缓存雪崩、缓存穿透、缓存击穿详解",{"children":10,"description":4,"id":38,"noteId":30,"parentId":14,"sort":6,"status":16,"title":39},"453168927736864768","Redis持久化：RDB与AOF原理、机制、用途、优缺点、混合持久化",{"children":10,"description":4,"id":41,"noteId":30,"parentId":14,"sort":42,"status":16,"title":43},"453169086310916096",2,"Redis 内存淘汰机制 8种策略+LRU、LFU底层原理",{"content":45,"contentType":46,"description":4,"title":43,"wordCount":47},"# Redis 内存淘汰机制（8种策略\\+LRU\u002FLFU底层原理）\n\nRedis 是内存数据库，**最大内存用完后必须淘汰数据**，否则无法写入新数据、直接 OOM。内存淘汰机制就是 Redis 内存满了之后「删谁、怎么删」的核心规则。\n\n本文覆盖：**maxmemory 机制、8种淘汰策略、LRU 近似实现原理、LFU 热点淘汰原理、LRU\u002FLFU 对比、生产选型、面试高频问法**。\n\n## 一、前置基础：maxmemory 触发条件\n\n### 1\\. 最大内存配置\n\nredis\\.conf 核心参数：\n\n- **maxmemory 10gb**：设置 Redis 最大可用内存\n\n- **maxmemory\\-policy**：内存满后的淘汰策略\n\n**默认行为**：不配置 maxmemory 时，64位Redis **不限制内存**，会一直吃满机器内存，导致机器卡死、OOM。\n\n### 2\\. 什么时候触发淘汰？\n\n每次执行 **写命令**（set、hset、incr、lpush 等）时：\n\n判断内存是否超出 maxmemory → 超出则执行对应淘汰策略，腾出空间后再写入新数据。\n\n## 二、Redis 八种内存淘汰策略（面试必背）\n\n分为三大类：**不淘汰、淘汰TTL、淘汰冷热**\n\n### 1\\. 禁止淘汰（默认策略）\n\n- **noeviction**：内存满后**不删除任何数据**，直接报错 OOM。\n\n**适用场景**：纯持久化、不允许丢数据的核心业务，生产基本不用。\n\n### 2\\. 只淘汰带过期时间的 key（TTL 策略）\n\n- **volatile\\-ttl**：在带过期的key中，优先删除 **剩余过期时间最短** 的（快到期先删）\n\n- **volatile\\-lru**：带过期key中，删除 **最久未使用**\n\n- **volatile\\-lfu**：带过期key中，删除 **访问频次最低**\n\n- **volatile\\-random**：带过期key中，随机删除\n\n特点：**永久key绝对不删**，只动有过期时间的缓存key。\n\n### 3\\. 全局淘汰（所有key，无论是否过期）\n\n- **allkeys\\-lru**：全局所有key，删除最久未使用（**生产最常用**）\n\n- **allkeys\\-lfu**：全局所有key，删除访问频次最低（Redis4\\.0\\+ 最优）\n\n- **allkeys\\-random**：全局随机删除，极度不推荐\n\n## 三、核心重点：Redis LRU 底层原理（面试深坑）\n\n**重要结论**：**Redis 并不是严格 LRU，是「近似 LRU」**！\n\n严格LRU需要维护链表、每次访问移动节点，**消耗巨大CPU**，Redis 为高性能做了轻量化优化。\n\n### 1\\. LRU 核心数据结构\n\n每个 Redis key 对象（redisObject）内部维护：\n\n- **lru 字段（24bit）**：记录该key **最后一次访问的时间戳**\n\n无需链表、无需排序，仅靠时间戳判断冷热。\n\n### 2\\. 近似 LRU 淘汰流程\n\n内存满需要淘汰时：\n\n1. 随机采样 **5个key**（默认参数 maxmemory\\-samples）\n\n2. 对比这5个key的 lru 时间戳\n\n3. 删除其中 **最久没访问** 的key\n\n4. 循环往复，直到内存够用\n\n**优点**：极高性能、几乎无CPU开销\n\n**缺点**：不是绝对精准，极个别冷门key可能侥幸存活，但误差极小，工程完全可用\n\n### 3\\. 采样参数说明\n\n`maxmemory-samples 5`\n\n采样值越大越精准、越耗CPU；5是性能与精度的最佳平衡点。\n\n## 四、Redis LFU 底层原理（Redis4\\.0\\+ 最强淘汰）\n\n**LFU：最少频次使用淘汰**，解决 LRU 的致命缺陷：**LRU只看时间、不看热度**。\n\n### 1\\. LRU 的缺陷\n\n举例：一个**高频热点key**刚刚10秒没人访问，一个**冷门key**刚刚被访问一次。\n\nLRU 会误删热点key、保留垃圾冷门key，**冷热判断失真**。\n\n### 2\\. LFU 字段结构（24bit）\n\nredisObject 的 lru 字段复用拆分：\n\n- **低 16bit：访问计数器 counter**：记录访问频次\n\n- **高 8bit：递减时间戳**：记录上一次衰减时间\n\n### 3\\. LFU 核心机制（智能衰减）\n\nLFU 不是简单累加计数，否则老key永远删不掉，核心是**热度衰减**：\n\n- key 长期不访问，计数器自动衰减变小\n\n- 新访问 key 计数上涨快\n\n- 真正实现：**淘汰长期冷门，保留持续热点**\n\n### 4\\. LFU 淘汰流程\n\n1. 随机采样若干key\n\n2. 对比访问频次 counter\n\n3. 删除频次最低的key\n\n4. 频次相同再比较访问时间\n\n## 五、LRU vs LFU 终极对比（面试高频）\n\n|维度|LRU|LFU|\n|---|---|---|\n|判断依据|最近访问时间|历史访问热度\\+时间衰减|\n|冷热识别|弱，容易误删热点|极强，精准识别真实热点|\n|新老key公平性|新key优势大|自动衰减，公平合理|\n|版本支持|全版本|4\\.0\\+|\n|生产推荐|通用场景|**高并发热点场景最优**|\n\n## 六、生产环境最佳策略选型（面试标准答案）\n\n1. **通用业务、绝大多数缓存场景**：`allkeys-lru`\n兼顾冷热淘汰、稳定、无副作用、运维友好\n\n2. **高并发热点业务（商品、榜单、首页）**：`allkeys-lfu`\n精准保留热点，淘汰僵尸冷数据，缓存命中率最高\n\n3. **希望永久key不被删除、只删过期缓存**：`volatile-lru`\n\n4. **不允许丢数据、纯存储业务**：`noeviction`，配合严格内存监控\n\n## 七、面试高频八股总结（直接背诵）\n\n- **Redis内存满了怎么办？** 触发内存淘汰策略，采样删除冷热key，腾出空间再写入。\n\n- **Redis LRU 是真LRU吗？** 不是严格LRU，是**采样式近似LRU**，靠对象24bit时间戳\\+随机采样淘汰，性能极高。\n\n- **LRU缺点？** 只看访问时间，不看访问频次，会误删短期未访问的热点key。\n\n- **LFU优势？** 基于访问热度\\+自动衰减，精准区分冷热数据，缓存命中率更高。\n\n- **为什么不用严格LRU？** 需要维护链表排序，CPU开销巨大，Redis追求极致性能。\n","markdown",2791,{"frontmatter":49,"meta":50,"nodes":117},{},{"title":51,"description":52,"toc":53},"Redis 内存淘汰机制（8种策略+LRU\u002FLFU底层原理）","Redis 是内存数据库，最大内存用完后必须淘汰数据，否则无法写入新数据、直接 OOM。内存淘汰机制就是 Redis 内存满了之后「删谁、怎么删」的核心规则。",{"title":4,"searchDepth":54,"depth":54,"links":55},5,[56,67,80,93,109,112,114],{"id":57,"depth":42,"text":58,"children":59},"maxmemory","一、前置基础：maxmemory 触发条件",[60,64],{"id":61,"depth":62,"text":63},"maxmemory-_1",3,"1. 最大内存配置",{"id":65,"depth":62,"text":66},"maxmemory-_2","2. 什么时候触发淘汰？",{"id":68,"depth":42,"text":69,"children":70},"redis","二、Redis 八种内存淘汰策略（面试必背）",[71,74,77],{"id":72,"depth":62,"text":73},"redis-_1","1. 禁止淘汰（默认策略）",{"id":75,"depth":62,"text":76},"redis-_2-keyttl","2. 只淘汰带过期时间的 key（TTL 策略）",{"id":78,"depth":62,"text":79},"redis-_3-key","3. 全局淘汰（所有key，无论是否过期）",{"id":81,"depth":42,"text":82,"children":83},"redis-lru","三、核心重点：Redis LRU 底层原理（面试深坑）",[84,87,90],{"id":85,"depth":62,"text":86},"redis-lru-_1-lru","1. LRU 核心数据结构",{"id":88,"depth":62,"text":89},"redis-lru-_2-lru","2. 近似 LRU 淘汰流程",{"id":91,"depth":62,"text":92},"redis-lru-_3","3. 采样参数说明",{"id":94,"depth":42,"text":95,"children":96},"redis-lfu-redis40","四、Redis LFU 底层原理（Redis4.0+ 最强淘汰）",[97,100,103,106],{"id":98,"depth":62,"text":99},"redis-lfu-redis40-_1-lru","1. LRU 的缺陷",{"id":101,"depth":62,"text":102},"redis-lfu-redis40-_2-lfu-24bit","2. LFU 字段结构（24bit）",{"id":104,"depth":62,"text":105},"redis-lfu-redis40-_3-lfu","3. LFU 核心机制（智能衰减）",{"id":107,"depth":62,"text":108},"redis-lfu-redis40-_4-lfu","4. LFU 淘汰流程",{"id":110,"depth":42,"text":111},"lru-vs-lfu","五、LRU vs LFU 终极对比（面试高频）",{"id":4,"depth":42,"text":113},"六、生产环境最佳策略选型（面试标准答案）",{"id":115,"depth":42,"text":116},"-1","七、面试高频八股总结（直接背诵）",[118,122,131,138,141,144,147,163,173,175,182,185,187,193,195,207,213,215,250,257,259,283,285,295,302,304,307,318,321,323,326,349,355,361,363,369,372,374,383,385,396,402,404,407,421,423,429,443,445,459,461,541,543,576,578],[119,120,51],"h1",{"id":121},"redis-8lrulfu",[123,124,125,126,130],"p",{},"Redis 是内存数据库，",[127,128,129],"strong",{},"最大内存用完后必须淘汰数据","，否则无法写入新数据、直接 OOM。内存淘汰机制就是 Redis 内存满了之后「删谁、怎么删」的核心规则。",[123,132,133,134,137],{},"本文覆盖：",[127,135,136],{},"maxmemory 机制、8种淘汰策略、LRU 近似实现原理、LFU 热点淘汰原理、LRU\u002FLFU 对比、生产选型、面试高频问法","。",[139,140,58],"h2",{"id":57},[142,143,63],"h3",{"id":61},[123,145,146],{},"redis.conf 核心参数：",[148,149,150,157],"ul",{},[151,152,153,156],"li",{},[127,154,155],{},"maxmemory 10gb","：设置 Redis 最大可用内存",[151,158,159,162],{},[127,160,161],{},"maxmemory-policy","：内存满后的淘汰策略",[123,164,165,168,169,172],{},[127,166,167],{},"默认行为","：不配置 maxmemory 时，64位Redis ",[127,170,171],{},"不限制内存","，会一直吃满机器内存，导致机器卡死、OOM。",[142,174,66],{"id":65},[123,176,177,178,181],{},"每次执行 ",[127,179,180],{},"写命令","（set、hset、incr、lpush 等）时：",[123,183,184],{},"判断内存是否超出 maxmemory → 超出则执行对应淘汰策略，腾出空间后再写入新数据。",[139,186,69],{"id":68},[123,188,189,190],{},"分为三大类：",[127,191,192],{},"不淘汰、淘汰TTL、淘汰冷热",[142,194,73],{"id":72},[148,196,197],{},[151,198,199,202,203,206],{},[127,200,201],{},"noeviction","：内存满后",[127,204,205],{},"不删除任何数据","，直接报错 OOM。",[123,208,209,212],{},[127,210,211],{},"适用场景","：纯持久化、不允许丢数据的核心业务，生产基本不用。",[142,214,76],{"id":75},[148,216,217,227,236,244],{},[151,218,219,222,223,226],{},[127,220,221],{},"volatile-ttl","：在带过期的key中，优先删除 ",[127,224,225],{},"剩余过期时间最短"," 的（快到期先删）",[151,228,229,232,233],{},[127,230,231],{},"volatile-lru","：带过期key中，删除 ",[127,234,235],{},"最久未使用",[151,237,238,232,241],{},[127,239,240],{},"volatile-lfu",[127,242,243],{},"访问频次最低",[151,245,246,249],{},[127,247,248],{},"volatile-random","：带过期key中，随机删除",[123,251,252,253,256],{},"特点：",[127,254,255],{},"永久key绝对不删","，只动有过期时间的缓存key。",[142,258,79],{"id":78},[148,260,261,271,277],{},[151,262,263,266,267,270],{},[127,264,265],{},"allkeys-lru","：全局所有key，删除最久未使用（",[127,268,269],{},"生产最常用","）",[151,272,273,276],{},[127,274,275],{},"allkeys-lfu","：全局所有key，删除访问频次最低（Redis4.0+ 最优）",[151,278,279,282],{},[127,280,281],{},"allkeys-random","：全局随机删除，极度不推荐",[139,284,82],{"id":81},[123,286,287,290,291,294],{},[127,288,289],{},"重要结论","：",[127,292,293],{},"Redis 并不是严格 LRU，是「近似 LRU」","！",[123,296,297,298,301],{},"严格LRU需要维护链表、每次访问移动节点，",[127,299,300],{},"消耗巨大CPU","，Redis 为高性能做了轻量化优化。",[142,303,86],{"id":85},[123,305,306],{},"每个 Redis key 对象（redisObject）内部维护：",[148,308,309],{},[151,310,311,314,315],{},[127,312,313],{},"lru 字段（24bit）","：记录该key ",[127,316,317],{},"最后一次访问的时间戳",[123,319,320],{},"无需链表、无需排序，仅靠时间戳判断冷热。",[142,322,89],{"id":88},[123,324,325],{},"内存满需要淘汰时：",[327,328,329,336,339,346],"ol",{},[151,330,331,332,335],{},"随机采样 ",[127,333,334],{},"5个key","（默认参数 maxmemory-samples）",[151,337,338],{},"对比这5个key的 lru 时间戳",[151,340,341,342,345],{},"删除其中 ",[127,343,344],{},"最久没访问"," 的key",[151,347,348],{},"循环往复，直到内存够用",[123,350,351,354],{},[127,352,353],{},"优点","：极高性能、几乎无CPU开销",[123,356,357,360],{},[127,358,359],{},"缺点","：不是绝对精准，极个别冷门key可能侥幸存活，但误差极小，工程完全可用",[142,362,92],{"id":91},[123,364,365],{},[366,367,368],"code",{},"maxmemory-samples 5",[123,370,371],{},"采样值越大越精准、越耗CPU；5是性能与精度的最佳平衡点。",[139,373,95],{"id":94},[123,375,376,379,380,137],{},[127,377,378],{},"LFU：最少频次使用淘汰","，解决 LRU 的致命缺陷：",[127,381,382],{},"LRU只看时间、不看热度",[142,384,99],{"id":98},[123,386,387,388,391,392,395],{},"举例：一个",[127,389,390],{},"高频热点key","刚刚10秒没人访问，一个",[127,393,394],{},"冷门key","刚刚被访问一次。",[123,397,398,399,137],{},"LRU 会误删热点key、保留垃圾冷门key，",[127,400,401],{},"冷热判断失真",[142,403,102],{"id":101},[123,405,406],{},"redisObject 的 lru 字段复用拆分：",[148,408,409,415],{},[151,410,411,414],{},[127,412,413],{},"低 16bit：访问计数器 counter","：记录访问频次",[151,416,417,420],{},[127,418,419],{},"高 8bit：递减时间戳","：记录上一次衰减时间",[142,422,105],{"id":104},[123,424,425,426,290],{},"LFU 不是简单累加计数，否则老key永远删不掉，核心是",[127,427,428],{},"热度衰减",[148,430,431,434,437],{},[151,432,433],{},"key 长期不访问，计数器自动衰减变小",[151,435,436],{},"新访问 key 计数上涨快",[151,438,439,440],{},"真正实现：",[127,441,442],{},"淘汰长期冷门，保留持续热点",[142,444,108],{"id":107},[327,446,447,450,453,456],{},[151,448,449],{},"随机采样若干key",[151,451,452],{},"对比访问频次 counter",[151,454,455],{},"删除频次最低的key",[151,457,458],{},"频次相同再比较访问时间",[139,460,111],{"id":110},[462,463,464,480],"table",{},[465,466,467],"thead",{},[468,469,470,474,477],"tr",{},[471,472,473],"th",{},"维度",[471,475,476],{},"LRU",[471,478,479],{},"LFU",[481,482,483,495,506,517,528],"tbody",{},[468,484,485,489,492],{},[486,487,488],"td",{},"判断依据",[486,490,491],{},"最近访问时间",[486,493,494],{},"历史访问热度+时间衰减",[468,496,497,500,503],{},[486,498,499],{},"冷热识别",[486,501,502],{},"弱，容易误删热点",[486,504,505],{},"极强，精准识别真实热点",[468,507,508,511,514],{},[486,509,510],{},"新老key公平性",[486,512,513],{},"新key优势大",[486,515,516],{},"自动衰减，公平合理",[468,518,519,522,525],{},[486,520,521],{},"版本支持",[486,523,524],{},"全版本",[486,526,527],{},"4.0+",[468,529,530,533,536],{},[486,531,532],{},"生产推荐",[486,534,535],{},"通用场景",[486,537,538],{},[127,539,540],{},"高并发热点场景最优",[139,542,113],{"id":4},[327,544,545,553,561,568],{},[151,546,547,290,550,552],{},[127,548,549],{},"通用业务、绝大多数缓存场景",[366,551,265],{},"\n兼顾冷热淘汰、稳定、无副作用、运维友好",[151,554,555,290,558,560],{},[127,556,557],{},"高并发热点业务（商品、榜单、首页）",[366,559,275],{},"\n精准保留热点，淘汰僵尸冷数据，缓存命中率最高",[151,562,563,290,566],{},[127,564,565],{},"希望永久key不被删除、只删过期缓存",[366,567,231],{},[151,569,570,290,573,575],{},[127,571,572],{},"不允许丢数据、纯存储业务",[366,574,201],{},"，配合严格内存监控",[139,577,116],{"id":115},[148,579,580,586,596,602,608],{},[151,581,582,585],{},[127,583,584],{},"Redis内存满了怎么办？"," 触发内存淘汰策略，采样删除冷热key，腾出空间再写入。",[151,587,588,591,592,595],{},[127,589,590],{},"Redis LRU 是真LRU吗？"," 不是严格LRU，是",[127,593,594],{},"采样式近似LRU","，靠对象24bit时间戳+随机采样淘汰，性能极高。",[151,597,598,601],{},[127,599,600],{},"LRU缺点？"," 只看访问时间，不看访问频次，会误删短期未访问的热点key。",[151,603,604,607],{},[127,605,606],{},"LFU优势？"," 基于访问热度+自动衰减，精准区分冷热数据，缓存命中率更高。",[151,609,610,613],{},[127,611,612],{},"为什么不用严格LRU？"," 需要维护链表排序，CPU开销巨大，Redis追求极致性能。"]