如何配置MemoryCache的MemoryCacheEntryOptions实现LRU缓存淘汰?
MemoryCache实现LRU缓存策略的问题解答
可以的,Microsoft.Extensions.Caching.Memory.MemoryCache 默认就支持**最近最少使用(LRU)**的缓存淘汰策略,你的现有配置已经满足基础要求,仅需注意几个细节:
核心逻辑说明
当你为MemoryCache设置SizeLimit,且每个缓存条目通过MemoryCacheEntryOptions.SetSize()指定大小后,一旦缓存总大小超过限制,MemoryCache会自动触发LRU淘汰——移除当前最近最少被访问(读取/写入)的条目,无需额外配置其他参数。
你的代码分析
正确配置点
- 缓存总容量限制:构造
MemoryCache时设置SizeLimit = 5,结合每个条目SetSize(1),意味着缓存最多保留5个条目。 - 条目大小设置:
SetValue方法中为每个条目指定大小为1,确保缓存能正确计算总占用空间,触发淘汰逻辑。
代码笔误修正
你的类MemoryCacheManagement的构造函数名称写成了MemoryCacheRepository,需要修正为与类名一致:
public class MemoryCacheManagement { private MemoryCache Cache { get; set; } public MemoryCacheManagement() { Cache = new MemoryCache(new MemoryCacheOptions { SizeLimit = 5 }); } public void SetValue<T>(string key, T value) { Cache.Set(key, value, new MemoryCacheEntryOptions() .SetSize(1) ); } // 新增Get方法用于验证缓存状态 public bool TryGetValue<T>(string key, out T value) { return Cache.TryGetValue(key, out value); } }
测试代码验证
你可以在测试中添加断言,验证LRU逻辑是否生效:
[Test] public void TestLRUBehavior() { var cache = new MemoryCacheManagement(); User[] users = new User[] { new User { Id = 1, Name = "User1", Age = 20 }, new User { Id = 2, Name = "User2", Age = 21 }, new User { Id = 3, Name = "User3", Age = 22 }, new User { Id = 4, Name = "User4", Age = 21 }, new User { Id = 5, Name = "User5", Age = 22 }, new User { Id = 6, Name = "User6", Age = 21 }, new User { Id = 1, Name = "User1", Age = 20 }, new User { Id = 7, Name = "User7", Age = 22 }, new User { Id = 2, Name = "User2", Age = 21 }, new User { Id = 3, Name = "User3", Age = 22 }, new User { Id = 2, Name = "User2", Age = 21 }, new User { Id = 3, Name = "User3", Age = 22 } }; foreach (var user in users) { cache.SetValue(user.Id.ToString(), user); } // 最终缓存应保留最近频繁访问的条目:1、2、3、6、7 Assert.IsTrue(cache.TryGetValue<User>("1", out _)); Assert.IsTrue(cache.TryGetValue<User>("2", out _)); Assert.IsTrue(cache.TryGetValue<User>("3", out _)); Assert.IsTrue(cache.TryGetValue<User>("6", out _)); Assert.IsTrue(cache.TryGetValue<User>("7", out _)); // 验证被LRU淘汰的条目:4、5 Assert.IsFalse(cache.TryGetValue<User>("4", out _)); Assert.IsFalse(cache.TryGetValue<User>("5", out _)); }
关键注意事项
- 任何对缓存条目的读取(
Get/TryGetValue)或写入(Set)操作,都会更新条目的"最近使用时间",确保LRU逻辑准确。 - 如果不设置条目大小,
SizeLimit不会生效,缓存不会触发自动淘汰。
内容的提问来源于stack exchange,提问作者Garry A
相关产品推荐
相关产品推荐

