Обновление IMemoryCache на стороне сервера - PullRequest
0 голосов
/ 07 января 2019

Я хочу кэшировать некоторые данные в нашем интернет-магазине на 1 час, и я использую Asp.Net Core 2.1 IMemoryCache. Можно ли обновлять кеш каждый час автоматически?

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

Я не могу найти IMemoryCache метод для этого. Я думаю, что это возможно с запланированной задачей, которая запускает некоторые функции обновления каждый час (+1 секунда?), Но затем, если повезет, запланированная задача немного позже, чем пользовательский запрос, и пользователь обновляет кэш вместо мое запланированное задание.

return _cache.GetOrCreate("FullNav", entry =>
{
    entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
    //calculate fullnav
    return fullnav;
});

Каков наилучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 07 января 2019

Наивная реализация:

    // add proper code to populate
    var x = "hello";
    _cache.Set(x, NullChangeToken.Singleton);

    Task.Factory.StartNew(async () =>
    {
        await Task.Delay(TimeSpan.FromHours(1));
        // add proper code to repopulate
        var y = "new value";
        _cache.Set(y, NullChangeToken.Singleton);
    });

Значение NullChangeToken никогда не изменится и, следовательно, значение не истечет автоматически. Значение будет заменено последующими вызовами на _cache.Set(...)

Реализация не учитывает, что элемент может быть очищен из-за нехватки памяти. Я думаю, что было бы лучше реализовать это как класс обслуживания, который создается как одиночный. Класс обслуживания сделал бы то же самое, но сохранил бы «дорогой» элемент в переменной экземпляра.

0 голосов
/ 10 января 2019

Лучший ответ, данный в комментариях Панагиотиса Канавоса:

  1. Используйте Set () вместо GetOrCreate () для принудительного сброса кеша, даже если он уже существует. Ссылка
  2. Не используйте время истечения, даже AbsoluteExpiration не требуется.
  3. Создать запланированное задание, которое вызывает этот метод каждый раз x

В коде:

fullnav = ''; //calculate fullnav
_cache.Set("FullNav",fullnav);

При вызове кешированного fullnav разумно использовать TryGetValue и вызывать метод set, когда кеш еще не доступен.

0 голосов
/ 07 января 2019

вы можете использовать AbsoluteExpiration

DateTime cacheEntry;

// Look for cache key.
if (!_cache.TryGetValue(CacheKeys.Entry, out cacheEntry))
{
    // Key not in cache, so get data.
    cacheEntry = DateTime.Now;

    // Set cache options.
    var cacheEntryOptions = new MemoryCacheEntryOptions()
        // Keep in cache for this time, reset time if accessed.
        .SetAbsoluteExpiration(TimeSpan.FromHours(1));

    // Save data in cache.
    _cache.Set(CacheKeys.Entry, cacheEntry, cacheEntryOptions);
}

return View("Cache", cacheEntry);

GetOrCreate версия, предложенная @Panagiotis Kavavos

var cacheEntry = _cache.GetOrCreate(CacheKeys.Entry, entry =>
{
    entry.AbsoluteExpiration = TimeSpan.FromHours(1);
    return DateTime.Now;
});

return View("Cache", cacheEntry);

Редактировать

AbsoluteExpiration

Получает или задает абсолютную дату окончания срока действия записи в кэше.

AbsoluteExpirationRelativeToNow

Получает или задает абсолютное время истечения, относительно текущего.

Rerefence

AbsoluteExpirationRelativeToNow зависит от времени, а AbsoluteExpiration от даты.

...