我试图在ASP.NET中为Web应用程序实现数据缓存,这是针对类的,我被要求限制ObjectCache中的条目数,而不是内存大小,而是通过条目本身的数量。这很简单,因为我可以调用ObjectCache.Count,但是当缓存超出既定限制(5,仅用于测试)时,我无法弄清楚如何删除存储的最旧元素,因为它按字母顺序排列排序
这是在数据访问层的服务中实现的,因此我无法使用任何其他结构(如队列)来跟踪缓存中的插入。
我该怎么办?有没有办法在缓存中过滤或获取旧元素?
这是方法代码
public List<EventSummary> FindEvents(String keywords, long categoryId, int start, int count)
{
string queryKey = "FindEvent-" + start + ":" + count + "-" + keywords.Trim() + "-" + categoryId;
ObjectCache cache = MemoryCache.Default;
List<EventSummary> val = (List<EventSummary>)cache.Get(queryKey);
if (val != null)
return val;
Category evnCategory = CategoryDao.Find(categoryId);
List<Event> fullResult = EventDao.FindByEventCategoryAndKeyword(evnCategory, keywords, start, count);
List<EventSummary> summaryResult = new List<EventSummary>();
foreach (Event evento in fullResult)
{
summaryResult.Add(new EventSummary(evento.evnId, evento.evnName, evento.Category, evento.evnDate));
}
if (cache.Count() >= maxCacheSize)
{
//WHAT SHOULD I DO HERE?
}
cache.Add(queryKey, summaryResult, DateTime.Now.AddDays(cacheDays));
return summaryResult;
}
答案 0 :(得分:0)
如评论中所述,Trim
method from MemoryCache
有一个LRU(最近最少使用)政策,这是您在此处寻找的行为。遗憾的是,该方法不是基于要从缓存中删除的绝对对象数,而是基于百分比,即int
参数。这只是意味着,如果你试图破解它并以1 / cache.Count()
作为百分比传递,你就无法控制真正从缓存中删除了多少对象,这不是一个理想的场景。
另一种方法是使用DIY方法,而不是使用.NET缓存实用程序,因为在我们的例子中,它们似乎并不完全符合您的需求。我正在考虑SortedDictionary的某些内容,其中缓存对象的时间代码作为键,并且在您给定值时,在给定时间码下插入缓存中的缓存对象列表。尝试重现您已经使用的.NET缓存行为并不是太大胆,并且自己直接控制删除策略的附加好处将是一个好的,IMO,并不是太大胆。
答案 1 :(得分:0)
作为旁注,与您的问题没有直接关系,
管理内存模型中缓存的最大问题是GC。
当您开始存储超过几百万个条目时,即使使用最先进的非阻塞GC,也会要求最终GC暂停。
很难缓存超过16 Gb,不会偶尔暂停5-6秒(即全部停止)。
我之前在此处描述过:https://stackoverflow.com/a/30584575/1932601 如果您需要存储非常多的过期条目(比如1亿条聊天消息),那么按原样缓存对象最终是一个糟糕的选择
看看我们做了多长时间存储数亿个对象而不杀死GC的做法。