更新 IMemoryCache 服务器端

Update IMemoryCache server-side

我想在我们的网上商店中缓存一些数据 1 小时,我正在使用 Asp.Net Core 2.1 IMemoryCache。是否可以每小时自动更新一次缓存?

正常情况下,当网络用户请求过期的缓存数据后,缓存会被刷新。但是缓存过程需要一些时间,我想确保没有用户获得 'slow' 网站,因为他的请求正在重置一些缓存数据。

我找不到任何 IMemoryCache 方法来执行此操作。我认为计划任务有可能每小时(+1 秒?)触发一些更新功能,但是运气不好,计划任务比用户请求晚一点,用户正在更新缓存而不是我的预定任务。

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

最好的方法是什么?

你可以使用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

Gets or sets an absolute expiration date for the cache entry.

AbsoluteExpirationRelativeToNow

Gets or sets an absolute expiration time, relative to now.

Rerefence

AbsoluteExpirationRelativeToNow 是特定于时间偏移的,而 AbsoluteExpiration 是特定于日期的。

天真的实现:

    // 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(...)

替换

实现没有考虑到项目可能因内存压力而被清除。我认为将其实现为实例化为单例的服务 class 可能会更好。服务 class 会做同样的事情,但将 "expensive" 项保留在实例变量中。

Panagiotis Kanavos 在评论中给出的最佳答案:

  1. 使用 Set() 而不是 GetOrCreate() 来强制重置缓存,即使它已经存在。 Link
  2. 不要使用过期时间,甚至不需要AbsoluteExpiration。
  3. 创建一个计划任务,每隔 x 次调用此方法

在代码中:

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

调用缓存的全导航时,明智的做法是使用TryGetValue并在缓存尚不可用时调用设置方法。