Когда Asp.Net удаляет устаревшие элементы кэша? - PullRequest
20 голосов
/ 16 сентября 2009

Когда вы добавляете элемент к System.Web.Caching.Cache с абсолютной датой истечения срока действия, как в следующем примере, как ведет себя Asp.Net? Делает это:

  1. Просто пометьте элемент как просроченный, затем выполните CacheItemRemovedCallback при следующей попытке доступа?

  2. Удалить элемент из кэша и немедленно выполнить CacheItemRemovedCallback?

    HttpRuntime.Cache.Insert(key,
                             new object(),
                             null, 
                             DateTime.Now.AddSeconds(seconds), 
                             Cache.NoSlidingExpiration,
                             CacheItemPriority.NotRemovable, 
                             OnCacheRemove);
    

MSDN указывает на то, что это происходит немедленно. Например, в разделе «Истечение срока действия» «Обзора кэширования ASP.NET» говорится: «ASP.NET автоматически удаляет элементы из кэша по истечении срока их действия». Аналогично, пример из темы «Как: уведомить приложение об удалении элемента из кэша» говорит «Если между вызовами GetReport проходит более 15 секунд [метод в примере] ASP.NET удаляет отчет из кэша. "

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

Тем не менее, мой тест был быстрым и грязным, и в комментариях к моему ответу на Есть ли способ запускать процесс каждый день в веб-приложении .Net без написания службы Windows или заданий сервера SQL кто-то предположил, что Asp.Net фактически откладывает удаление и выполнение обратного вызова до тех пор, пока что-то не попытается снова получить доступ к кешу.

Может кто-нибудь уладить это авторитетно или это просто считается деталью реализации?

Ответы [ 2 ]

37 голосов
/ 18 сентября 2009

Ура для Отражатель !

Истекшие элементы кэша фактически удалены (и вызваны обратные вызовы), если либо:

1) Что-то пытается получить доступ к элементу кэша.

2) Метод ExpiresBucket.FlushExpiredItems запускается и попадает в элемент. Этот метод жестко запрограммирован на выполнение каждые 20 секунд (принятый ответ на вопрос StackOverflow Изменение частоты истечения срока действия элемента кэша ASP.NET подтверждает мое чтение этого кода с помощью Reflector). Однако для этого требуется дополнительная квалификация (для чего читайте дальше).


Asp.Net поддерживает один кэш для каждого процессора на сервере (я не уверен, представляют ли они логические или физические процессоры); каждый из них поддерживает экземпляр CacheExpires, имеющий соответствующий Timer, который вызывает свой метод FlushExpiredItems каждые двадцать секунд.

Этот метод выполняет последовательную итерацию по другому набору «сегментов» данных об истечении срока действия кэша (массив ExpiresBucket экземпляров) последовательно, вызывая метод каждого сегмента FlushExpiredItems по очереди.

Этот метод (ExpiresBucket.FlushExpiredItems) сначала выполняет итерацию всех элементов кэша в корзине, и, если срок действия элемента истек, отмечается, что он истек. Затем (я сильно упрощаю здесь) он перебирает элементы, которые он пометил, истек, и удаляет их, выполняя CacheItemRemovedCallback (фактически, он вызывает CacheSingle.Remove, который вызывает CacheInternal.DoRemove, затем CacheSingle.UpdateCache, затем CacheEntry.Close , который фактически вызывает обратный вызов).

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

Однако при этом временном разрешении с минимальным интервалом истечения в двадцать секунд единственной частью процесса, которая может блокироваться в течение значительного промежутка времени, является выполнение CacheItemRemovedCallbacks. Любой из них может блокировать поток Timer FlushExpiredItems на неопределенный срок. (Хотя через двадцать секунд Timer породит еще один FlushExpiredItems поток.) ​​

Подводя итог, можно сказать, что Asp.Net не гарантирует , что он будет выполнять обратные вызовы в указанное время, но при определенных условиях. Пока интервалы истечения находятся на расстоянии более двадцати секунд, и пока кэш не должен выполнять длительное время CacheItemRemovedCallbacks (глобально - любые обратные вызовы могут потенциально помешать другим), он может выполнять обратные вызовы истечения на график. Это будет достаточно для некоторых приложений, но не подходит для других.

5 голосов
/ 17 сентября 2009

Истекшие элементы не сразу удаляются из кэша, они просто помечаются как просроченные. Вы не получите обратный вызов, пока не пропустите кеш. Я столкнулся с этим в ASP.NET 1.1 дней, , и он не изменился .

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

Я обычно использую таймер, который регулярно перезагружает кеш.

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