You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.NET Core 2.0中IMemoryCache未按预期缓存至下周一,仅维持1小时的问题

问题分析与解决方案

嘿,咱们先把你的核心疑问解决掉:这个问题和Token有效期完全没关系!你缓存的是GetRanking的查询结果数据,和Token(不管是JWT还是数据库连接Token)的有效期没有直接关联——如果是Token过期导致的问题,你应该会收到数据库连接或授权错误,而不是成功重新从数据库拉取数据。

接下来咱们看真正的问题所在,以及怎么修复:

一、缓存失效的可能原因

你的代码逻辑看起来是想让缓存维持到下周一,但实际只撑1小时,大概率是以下两种情况:

  1. 进程内缓存的局限性
    IMemoryCache是进程内缓存,一旦你的.NET Core应用程序重启(比如服务器应用池设置了1小时自动回收、代码部署更新、内存不足触发进程重启),缓存就会被清空,不得不重新从数据库拉取数据。
  2. 缓存过期时间的设置逻辑有瑕疵
    你当前用TimeSpan.FromDays(diff)设置相对过期时间,但这种方式是从当前时间往后推N天,而不是固定到下周一的零点。另外,当计算diff时,周日的情况会出现逻辑偏差(比如周日时daysToStartWeek = DayOfWeek.Sunday - DayOfWeek.Monday = -1diff会算出1,导致缓存只维持1天)。

二、修正后的代码方案

要实现「每周一自动更新缓存」的需求,更可靠的方式是设置绝对过期时间(固定到下周一的零点),同时优化缓存项的优先级,避免内存不足时被提前回收。修改后的代码如下:

var dateNow = DateTime.Now;
DateTime nextMonday;

if (dateNow.DayOfWeek == DayOfWeek.Monday)
{
    // 今天是周一,缓存到下周一的零点
    nextMonday = dateNow.AddDays(7).Date;
}
else
{
    // 计算距离下周一的天数,逻辑更简洁准确
    int daysUntilMonday = ((int)DayOfWeek.Monday - (int)dateNow.DayOfWeek + 7) % 7;
    nextMonday = dateNow.AddDays(daysUntilMonday).Date;
}

// 先尝试从缓存获取
if (_cache.TryGetValue("GetRanking", out IEnumerable<GetRankingStruct> objRanking))
{
    return Ok(objRanking);
}

// 缓存未命中,从数据库拉取
var dp = new DataProvider(Configuration);
var response = dp.GetRanking(userName, asAtDate);

// 设置缓存:绝对过期到下周一零点,高优先级防止被提前回收
_cache.Set("GetRanking", response, new MemoryCacheEntryOptions
{
    AbsoluteExpiration = nextMonday,
    Priority = CacheItemPriority.High
});

return Ok(response);

三、额外排查建议

如果修改后还是出现1小时缓存失效的情况,你需要检查:

  • 服务器的应用池设置:是否开启了1小时自动回收?如果是,要么调整回收时间,要么改用分布式缓存(比如Redis)来避免进程重启丢失缓存。
  • 其他代码逻辑:有没有其他地方调用了_cache.Remove("GetRanking")或者更新了这个缓存键?
  • 内存压力:服务器是否内存不足?IMemoryCache会在内存紧张时自动回收低优先级的缓存项,所以我们设置了Priority = CacheItemPriority.High来降低这种风险。

内容的提问来源于stack exchange,提问作者Aless Hosry

火山引擎 最新活动