Как удалить просроченные элементы из кеша?

У меня есть хороший маленький класс, который действует как кеш. Каждый элемент имеет срок действия TimeSpan или DateTime. Каждый раз, когда предпринимается попытка доступа к элементу в кеше, проверяется срок действия элемента, и если он истек, элемент удаляется из кеша и ничего не возвращается.

Это отлично подходит для объектов, к которым часто обращаются, но если элемент помещается в кеш и больше никогда не используется, он никогда не удаляется, даже если срок его действия истек.

Какова хорошая методология для удаления таких элементов из кеша?

Должен ли я иметь фоновый поток, бесконечно перечисляющий каждый элемент в кеше, чтобы проверить, не истек ли срок его действия?


person core    schedule 26.09.2008    source источник
comment
Это кеш фиксированного размера? Если это так, я не вижу проблем с оставлением элементов в кеше.   -  person Ryan Guest    schedule 26.09.2008


Ответы (5)


arrow_upward
1
arrow_downward

По моему опыту, поддержание пользовательского механизма кэширования доставляло больше хлопот, чем оно того стоило. Есть несколько библиотек, которые уже решили эти проблемы. Я бы предложил использовать один из них. Популярной в .Net является Enterprise Library, хотя у меня ограниченный опыт работы с ее возможностями кэширования.

Если вы должны использовать собственный механизм кэширования, то я не вижу проблем с предложенной вами идеей бдительного потока. То есть, если ваше приложение является серверным, а не веб-приложением. Если это веб-приложение, у вас уже есть встроенный скользящий срок действия. Затем вы можете просто обернуть его в строго типизированную оболочку, чтобы каждый раз не ссылаться на элементы кеша по ключу.

person Kilhoffer    schedule 26.09.2008

arrow_upward
5
arrow_downward

Лучший код — это отсутствие кода. Вместо этого используйте кеш ASP.NET. Вы можете ссылаться на него как на System.Web.HttpRuntime.Cache в любом приложении, а не только в веб-приложениях.

person Joe    schedule 26.09.2008
comment
Что, если сборка использует HttpRuntime.Cache в двух разных местах? Они используют один и тот же кеш, верно? В таком случае это не сработает, к сожалению. Он уже используется, и поэтому я не могу гарантировать, что мои предметы не будут удалены. - person core; 03.10.2008
comment
Я не понимаю вашего комментария. Для каждого AppDomain существует один объект HttpRuntime.Cache. Если вы вставляете элементы в кэш в двух разных местах, вы должны использовать разные ключи — это справедливо для любого решения. Можете ли вы уточнить? - person Joe; 03.10.2008
comment
Текущей альтернативой, если вы можете использовать платформу 4.0, является Кэш памяти. Это нарушает зависимость от ASP.Net, и у вас может быть несколько экземпляров, но для этого требуется полная платформа 4.0. - person Kevin Pullin; 20.02.2011

arrow_upward
1
arrow_downward

Вы можете внедрить стратегию LRU (наименее недавно использованная), сортировать элементы по времени доступа, когда новый элемент вставляется в кеш и кеш заполняется, вы удаляете последний элемент в этом список. См. алгоритмы кэширования в Википедии.

Если вы хотите немедленно истечь, я бы все равно делал это только при доступе к вещам. т.е. когда к объекту кеша обращаются и его время истекло, обновите его.

person Harald Scheirich    schedule 26.09.2008

arrow_upward
1
arrow_downward

Вы также можете при любом изменении кэша (повторно) запустить таймер с интервалом, установленным на ближайшую отметку времени истечения срока действия. Это не будет точно до миллисекунд и зависит от работы насоса сообщений, но не очень требовательно к ресурсам.

Однако ответ Харальда Шейриха лучше, если вы не возражаете против того, что объекты висят вечно, когда кеш не обновляется.

person OregonGhost    schedule 26.09.2008

arrow_upward
1
arrow_downward

Вы можете удалить достаточно старые элементы из кеша при первом доступе через 1 минуту после последней очистки элементов.

private DateTime nextFlush;
public object getItem(object key)
{
  DateTime now = DateTime.Now
  if (now > nextFlush)
  {
    Flush();
    nextFlush = now.AddMinutes(1)
  }
  return fetchItem(key);
}
person Amy B    schedule 26.09.2008