使用CacheManager,您最好如何实施此方案,其中缓存实例包含数据,这可能需要很长时间才能从慢速来源获取?
我从不希望用户等待缓存填充(我不担心第一次加载)
我可以想到两种方法,但不确定它们是否可以使用CacheManager:
Cachemanager技术上可行的是什么,哪种方法效果最好 - 如果有的话?
答案 0 :(得分:2)
关于您的第二个选项“在到期时刷新”,这不起作用,因为如果项目过期,CacheManager不会返回缓存的值。而且,当您“刷新”缓存时,您最终会从其他调用者那里获得大量缓存未命中。
我的建议:
如果您只有少量密钥缓存60分钟且它们都“工作相同”,只需启动一个后台任务,该任务对您的进程运行异步,并每15分钟刷新一次缓存。
如果您有许多密钥在到期时可能会有很大变化,您可以在60分钟到期时缓存数据,并存储一个二级密钥(一个没有实际值的假密钥),到期时间为15分钟。然后,如果假密钥到期,刷新实际的键/值...
作为假的key
,例如使用前缀+实际键,然后听取OnRemove
事件。
快速示例程序
internal class Program
{
private static ICacheManager<object> _cache;
private static void Main(string[] args)
{
_cache = CacheFactory.Build(c => c.WithDictionaryHandle());
_cache.OnRemoveByHandle += Cache_OnRemoveByHandle;
for (var i = 0; i < 10; i++)
{
_cache.Add("key" + i, "data" + i);
AddFakeKey("key" + i);
Thread.Sleep(1000);
}
Console.ReadKey();
}
private static void AddFakeKey(string forKey)
{
_cache.Add(new CacheItem<object>("trigger_" + forKey, "n/a", ExpirationMode.Absolute, TimeSpan.FromSeconds(1)));
}
private static void Cache_OnRemoveByHandle(object sender, CacheItemRemovedEventArgs e)
{
// Remark: you might get this event triggered for each level of the cache e.Level can be checked to react only on the lowest level...
Console.WriteLine("OnRemoveByHandle " + e.ToString());
if (e.Key.StartsWith("trigger_") && e.Reason == CacheItemRemovedReason.Expired)
{
var key = e.Key.Substring(8);
Console.WriteLine("Updating key " + key);
// updating the key
_cache.Update(key, _ => "new value");
// add a new fake key for another round
AddFakeKey(key);
}
}
}
如果启用了密钥空间通知,这甚至适用于Redis。
答案 1 :(得分:1)
我没有安静地得到你的&#34;预定&#34;刷新的想法,为什么设置缓存在60分钟后过期并每15分钟刷新一次?
如果我是你,我会这样做(就像你的第二个想法一样):
您首次填充CacheManager,然后每隔60分钟填充一次新的CacheManager实例(并填充它),如果一切顺利,您可以替换旧实例(您也可以将其丢弃)。
我想到了这一点,因为在CacheManager中,过期的项目不会被自动删除,因此它们仍然存在,如果您决定执行类似[Populate-ClearAll-Populate- ..]的操作,那么您可能会得到解决一些问题,所以最安全的方法是在每次刷新时创建一个新实例,以确保你的缓存始终有效。