问题描述
下面的代码在本地主机上按预期工作,基本上我检查缓存键是否存在它返回值,如果不存在,它从数据库中获取值然后我设置2个缓存键,如果主缓存过期我返回备份键和再次启动设置主缓存的任务,此操作的目的是我不想在缓存过期后等待数据库调用,而是返回备份键并再次设置主键。 问题是,这段代码在本地机器上工作,在调试模式下,它在设置后返回缓存,如果它在缓存中,代码不会调用 sql,但在服务器上似乎 memorycache 失败了,因为在 ssms 上我检查上次执行的查询,每当我需要这些数据,它会再次运行查询。在调试模式下,它不会再次运行查询。这是怎么回事,环境是.net core 2.2。
public async Task<MenuList> GetMenus()
{
try
{
if (_cache.TryGetValue(_menusCacheKey,out MenuList menus))
{
return menus;
}
else
{
if (_cache.TryGetValue(_menusBackupCacheKey,out MenuList _menusBackup))
{
new Task(() =>
{
var getMenus = JsonConvert.DeserializeObject<List<viewmodels.Menu.Menu>>(_apiclient.Post(_appSettings.Api.Endpoints.GetMenus,1).Result);
var menuItemPerCol = (int)GetSettings("MenuItemPerCol");
var model = new MenuList();
model.Menus = getMenus;
model.MenuItemPerCol = menuItemPerCol;
_cache.Set(_menusCacheKey,model,_menuCacheExpiration);
_cache.Set(_menusBackupCacheKey,model);
}).Start();
return _menusBackup;
}
var getMenusG = JsonConvert.DeserializeObject<List<viewmodels.Menu.Menu>>(await _apiclient.Post(_appSettings.Api.Endpoints.GetMenus,1));
var menuItemPerColG = (int)GetSettings("MenuItemPerCol");
var modelG = new MenuList();
modelG.Menus = getMenusG;
modelG.MenuItemPerCol = menuItemPerColG;
_cache.Set(_menusBackupCacheKey,modelG);
return _cache.Set(_menusCacheKey,modelG,_menuCacheExpiration);
}
}
这是我的 MenuList 类;
public class MenuList
{
public MenuList()
{
Menus = new List<Menu>();
}
public List<Menu> Menus { get; set; }
public int MenuItemPerCol { get; set; }
}
解决方法
一个不需要您做任何额外工作的解决方案是使用 FusionCache ⚡?,这是我最近发布的一个库。
它拥有您正在寻找的东西,这要归功于 2 个功能的组合:fail-safe + advanced timeouts 与后台工厂完成。
简而言之:你可以缓存一些东西,比方说,2 分钟后会调用一个工厂来刷新数据,但是,如果出现问题(异常、超时等),过期的值将被再次使用,直到工厂可以在后台完成,之后它会立即更新缓存。
这是一个示例调用:
$item->get_order_id()
FusionCache 还具有您可能会感兴趣的其他功能,例如避免针对同一个键同时使用 multiple concurrent factory calls 的优化(当多个线程尝试同时访问同一个缓存条目时很有用)。
另一个有趣的功能是支持可选的分布式 2nd level 缓存,无需执行任何操作即可自动管理并与本地缓存保持同步。
如果你愿意,请告诉我你的想法。
/无耻插头