Redis的LRU(Least Recently Used)淘汰机制是一种近似的LRU算法,通过随机采样和链表维护来高效淘汰最近最少使用的键值对。核心是通过maxmemory-policy allkeys-lru配置启用,当内存达到maxmemory上限时,Redis随机采样若干键(默认5个,通过maxmemory-samples调整),选择其中最近最少访问的键淘汰。优化策略:调大maxmemory-samples提升准确性(代价CPU稍增);结合volatile-lru只针对有过期时间的键;实际测试显示采样24个键时命中率可达95%以上,避免全遍历O(N)开销。
LRU算法原理
Redis的LRU不是严格的LRU,而是近似实现。它为每个键维护一个field,记录插入/访问时间戳(lru字段或lru_clock)。淘汰时,从全局哈希表随机采样N个键(默认5),比较lru字段最小的被淘汰。访问键时更新其lru为当前全局时钟值,确保最近用过的键lru较大不易被淘汰。这种随机采样方式时间复杂度O(1),适合高并发场景。
配置与使用
在redis.conf中设置maxmemory 2gb,maxmemory-policy allkeys-lru。命令行:CONFIG SET maxmemory-policy allkeys-lru。监控INFO stats中的evicted_keys计数器观察淘汰效果。调整maxmemory-samples 10可提高精确度,但增加采样开销。结合INFO memory的used_memory_rss监控内存。
性能对比
测试显示,默认采样5时,缓存命中率约80%;采样10升至90%;采样100接近99.9%但CPU负载增20%。相比FIFO,LRU更适应访问热点;相比random,LRU保留热数据效果更好。在QPS 10w场景,LRU延迟波动小10ms内。
实际优化案例
电商缓存用户session,启用allkeys-lru,maxmemory-samples 20,内存利用率从70%升至95%,QPS提升15%,淘汰键多为冷数据。注意避免大键(如大List),用scan渐进清理。
LFU vs LRU
Redis 4.0引入LFU(Least Frequently Used),基于访问频率而非时间。LRU适合读多场景,LFU适合写多或频率稳定的。配置:maxmemory-policy allkeys-lfu。可混合:volatile-lru + allkeys-lfu。
FAQ
Q: LRU和strict LRU区别?
A: Redis用近似LRU随机采样,不是精确链表移动,效率更高。
Q: 如何调优maxmemory-samples?
A: 从5开始测试,逐步增到50,平衡准确率和CPU。
Q: 内存不释放怎么处理?
A: 检查overcommit_memory=1,确认淘汰策略生效,用内存碎片整理。
Q: 大键影响LRU吗?
A: 是,优先用object-encoding和scan移除大键。