Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 更新IMemoryCache服务器端_.net_Asp.net Core_.net Core_Asp.net Core Mvc_Asp.net Core 2.1 - Fatal编程技术网

.net 更新IMemoryCache服务器端

.net 更新IMemoryCache服务器端,.net,asp.net-core,.net-core,asp.net-core-mvc,asp.net-core-2.1,.net,Asp.net Core,.net Core,Asp.net Core Mvc,Asp.net Core 2.1,我想在我们的网店中缓存一些数据1小时,我正在使用Asp.Net Core 2.1IMemoryCache。是否可以每小时自动更新一次缓存 通常,当webuser请求缓存的数据过期后,缓存将被刷新。但是缓存过程需要一些时间,我想确保没有用户会因为他的请求重置一些缓存数据而得到一个“慢”的网站 我找不到任何IMemoryCache方法来执行此操作。我认为计划任务每小时(+1秒?)触发一些更新功能是可能的,但如果运气不好,计划任务只是比用户请求晚一点,用户正在更新缓存,而不是我的计划任务 return

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

通常,当webuser请求缓存的数据过期后,缓存将被刷新。但是缓存过程需要一些时间,我想确保没有用户会因为他的请求重置一些缓存数据而得到一个“慢”的网站

我找不到任何
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
version,由@Panagiotis Kavavos建议

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

return View("Cache", cacheEntry);
编辑

绝对过期

获取或设置缓存项的绝对过期日期

绝对到期相对现在

获取或设置相对于现在的绝对过期时间

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
永远不会更改,因此该值不会自动过期。该值将被对
\u cache.Set(…)


该实现没有考虑到该项可能由于内存压力而被清除。我认为最好将其实现为一个服务类,并将其实例化为单例。服务类也会做同样的事情,但会将“昂贵”项保留在实例变量中。

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

  • 使用Set()而不是GetOrCreate()强制重置缓存,即使缓存已经存在
  • 不要使用过期时间,即使绝对过期也是不必要的
  • 创建每x次调用此方法的计划任务
  • 代码:

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

    调用缓存的fullnav时,最好使用
    TryGetValue
    并在缓存不可用时调用set方法。

    您可以尝试使用
    RegisterPostVictionCallback
    方法注册一个将重新填充缓存的回调:是否检查了这些方法?或者使用而不是
    AbsoluteExpirationRelativeToNow
    ?您可能根本不应该使用基于时间的过期,或者至少不应该使用比计划作业长的期限,因此条目将仅由计划作业替换。如果在启动过程中预热缓存,您只需担心由于内存压力而逐出条目使用分布式内存缓存,如redis。只需对其进行写入(无过期),当我们的数据发生更改(即用户编辑产品说明)时,生成新数据并更新缓存,这样您的缓存就永远不会过期。或者,当数据发生更改时,将生成的数据存储在数据库(或文件系统)中,然后在缓存未命中时从那里检索数据。这种方式在后端生成,其中on-cache未命中处理时间保持在最小值,只从db或sql读取数据filesystem@PanagiotisKanavos我没有找到集合函数,并期望AbsoluteExpiration和AbsoluteExpirationRelativeToNow的功能几乎相同(因为我想从现在起将项目缓存1小时,所以我选择了第二个。但我想你的意思是,这是设置无过期时间的最佳方法,并在计划任务中使用set函数重新计算缓存值,对吗?
    GetOrCreate
    with
    AbsoluteExpiration
    在这种情况下更安全。使用
    TryGet
    一个race-co如果两个或多个请求尝试进行相同的调用,则返回ndition。此代码将只执行原始问题中的代码所执行的操作。使用更多代码行也会降低线程安全性。OP使用的是
    AbsoluteExpirationRelativeToNow
    ,正如我所建议的
    AbsoluteExpiration
    我认为面临的主要问题是OP的意思是,当用户试图在项目被清除后从缓存中获取项目时,他希望避免“冷缓存”延迟。此代码解决了该问题吗?@mortb不设置过期期限将解决该问题