Использование кеша в ASP.NET - PullRequest
1 голос
/ 10 марта 2012

Я пытаюсь использовать кеш в веб-приложении ASP.NET MVC для хранения некоторых данных списка, которые редко обновляются.Я вставляю эти данные в кеш методом UpdateCache() следующим образом:

HttpContext.Current.Cache.Insert("MyApp-Products", products, null, DateTime.Now.AddYears(99), Cache.NoSlidingExpiration);

Затем в моей модели я получаю их:

public static List<string> GetProducts()
{
    var cachedProducts = HttpContext.Current.Cache["MyApp-Products"];
    if (cachedProducts == null)
    {
        UpdateCache();
        cachedProducts = HttpContext.Current.Cache["MyApp-Products"];
    }
    return ((List<string>)cachedProducts );
}

При первом посещении страницы,UpdateCache() называется как ожидалось.Если я обновляюсь, данные поступают из кеша, и мне не нужно звонить UpdateCache().Однако через 15 минут я возвращаюсь в приложение, и кэшированные значения исчезают.Насколько я понимаю, этот кэш был для каждого приложения, а не для сеанса, поэтому я ожидал, что он все еще будет там для меня или другого пользователя.

Что-то не так с тем, как я храню кеш?Или я что-то не понимаю в том, как Cache в ASP.NET работает в веб-приложении?

Ответы [ 3 ]

5 голосов
/ 10 марта 2012

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

Пока кэш для каждого приложенияASP.NET не дает вам никаких гарантий, что если вы сохраните что-то в кеше, то найдете его там.Кеш может быть удален при различных обстоятельствах, таких как, например, у вашего сервера заканчивается память и так далее.Вы можете подписаться на событие и получать уведомления, когда элемент выгружается из кэша.Вы также можете определить приоритет при кэшировании элемента.Чем выше приоритет, тем ниже вероятность выселения этого предмета.

Кроме того, поскольку кеш хранится в памяти веб-сервера (по умолчанию), вы не должны забывать тот факт, что домен приложения может быть переработан в любой момент IIS.Например, после определенного периода бездействия, или если он начинает исчерпывать память, или даже если достигнут определенный порог использования ЦП, ... и все, что хранится в памяти, включая кеш, просто исчезнет в пустоте и следующем запросев вашем приложении запустится новый домен приложений.

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

Все это блабла, чтобы прийти к действительно важному моменту, который очень беспокоит ваш код.Похоже, вы храните экземпляр List<string> в кэше.Но поскольку кэш-память для каждого приложения, этот единственный экземпляр List<string> может быть разделен между несколькими пользователями приложения, и, конечно, это может происходить одновременно.И, как вы знаете, List<T> не является потокобезопасной структурой.Таким образом, с этим кодом вы в лучшем случае получите исключение, а в худшем - поврежденные данные.Поэтому будьте очень осторожны с тем, что вы кэшируете и как синхронизируете доступ к структуре, особенно если вы кэшируете не поточно-безопасный класс.

2 голосов
/ 10 марта 2012

ЕСЛИ это на полном IIS, и происходит примерно каждые 15 минут. Не забудьте проверить значение времени ожидания простоя.

При этом, если этот список "никогда" не меняется, почему бы не сохранить его в статическом массиве.

0 голосов
/ 10 марта 2012

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

Попробуйте явно установить абсолютный срок действия при кэшировании объекта:

HttpRuntime.Cache.Insert("MyApp-Products", cachedProducts, null, DateTime.Now.AddDays(20), TimeSpan.Zero );

Примечание HttpRuntime используется вместо HttpContext по соображениям производительности, хотя разница незначительна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...