- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
从 MemoryCache 实例中删除大量项目的推荐方法是什么?
基于围绕 this question 的讨论似乎首选方法是对整个应用程序使用单个缓存,并使用命名空间作为键,以允许在同一实例中缓存多个逻辑类型的项目。
但是,使用单个缓存实例会带来缓存中大量项目过期(删除)的问题。特别是在某种逻辑类型的所有项目都必须过期的情况下。
目前我找到的唯一解决方案是基于 answer to this question但从性能的角度来看,这确实不是很好,因为您必须枚举缓存中的所有键,并测试命名空间,这可能非常耗时!
我目前想到的唯一解决方法是为缓存中的所有对象创建一个带有版本号的瘦包装器,并且每当访问对象时,如果缓存的版本与版本号不匹配,则丢弃它当前版本。因此,每当我需要清除某种类型的所有项目时,我都会提高当前版本号,使所有缓存的项目无效。
上面的解决方法看起来相当可靠。但我忍不住想知道是否有更直接的方法来完成同样的任务?
这是我当前的实现:
private class MemCacheWrapper<TItemType>
where TItemType : class
{
private int _version;
private Guid _guid;
private System.Runtime.Caching.ObjectCache _cache;
private class ThinWrapper
{
public ThinWrapper(TItemType item, int version)
{
Item = item;
Version = version;
}
public TItemType Item { get; set; }
public int Version { get; set; }
}
public MemCacheWrapper()
{
_cache = System.Runtime.Caching.MemoryCache.Default;
_version = 0;
_guid = Guid.NewGuid();
}
public TItemType Get(int index)
{
string key = string.Format("{0}_{1}", _guid, index);
var lvi = _cache.Get(key) as ThinWrapper;
if (lvi == null || lvi.Version != _version)
{
return null;
}
return lvi.Item;
}
public void Put(int index, TItemType item)
{
string key = string.Format("{0}_{1}", _guid, index);
var cip = new System.Runtime.Caching.CacheItemPolicy();
cip.SlidingExpiration.Add(TimeSpan.FromSeconds(30));
_cache.Set(key, new ThinWrapper(item, _version), cip);
}
public void Clear()
{
_version++;
}
}
最佳答案
我建议从 MemoryCache 实例中删除大量项目的方法是使用 ChangeMonitor ,特别是CacheEntryChangeMonitor .
Provides a base class that represents a ChangeMonitor type that can be implemented in order to monitor changes to cache entries.
因此,它允许我们处理缓存项之间的依赖关系。
一个非常基本的例子是
var cache = MemoryCache.Default;
cache.Add("mycachebreakerkey", "mycachebreakerkey", DateTime.Now.AddSeconds(15));
CacheItemPolicy policy = new CacheItemPolicy();
policy.ChangeMonitors.Add(cache.CreateCacheEntryChangeMonitor(new string[] { "mycachebreakerkey" }));
// just to debug removal
policy.RemovedCallback = args => { Debug.WriteLine(args.CacheItem.Key + "-->" + args.RemovedReason); };
cache.Add("cacheKey", "cacheKey", policy);
// after 15 seconds mycachebreakerkey will expire
// dependent item "cacheKey" will also be removed
对于大多数事情,您还可以创建自定义缓存实现或派生的更改监视器类型。
未经测试,但 CreateCacheEntryChangeMonitor 建议您可以在 MemoryCache 之间创建依赖关系。
编辑
ChangeMonitor 是使运行时缓存中的内容失效的 .net 方法。 Invalidate 这里的意思是=从缓存中删除。 SqlDependency 或一些 asp.net 组件使用它来监视文件更改。所以,我认为这个解决方案是可扩展的。
这是一个非常简单的基准测试,在我的笔记本电脑上运行。
const int NbItems = 300000;
var watcher = Stopwatch.StartNew();
var cache = MemoryCache.Default;
var breakerticks = 0L;
var allticks = new List<long>();
cache.Add("mycachebreakerkey", "mycachebreakerkey", new CacheItemPolicy() { RemovedCallback = args => { breakerticks = watcher.ElapsedTicks; } });
foreach (var i in Enumerable.Range(1, NbItems))
{
CacheItemPolicy policy = new CacheItemPolicy();
if (i % 4 == 0)
policy.ChangeMonitors.Add(cache.CreateCacheEntryChangeMonitor(new string[] { "mycachebreakerkeyone" }));
policy.RemovedCallback = args => { allticks.Add(watcher.ElapsedTicks); };// just to debug removal
cache.Add("cacheKey" + i.ToString(), "cacheKey", policy);
}
cache.Remove("mycachebreakerkey");
Trace.WriteLine("Breaker removal=>" + TimeSpan.FromTicks(breakerticks).TotalMilliseconds);
Trace.WriteLine("Start removal=>" + TimeSpan.FromTicks(allticks.Min()).TotalMilliseconds);
Trace.WriteLine("End removal=>" + TimeSpan.FromTicks(allticks.Max()).TotalMilliseconds);
Trace.WriteLine(cache.GetCount());
// Trace
// Breaker removal: 225,8062 ms
// Start removal: 0,251 ms
// End removal: 225,7688 ms
// 225000 items
因此,删除 300 000 个项目中的 25% 需要 225 毫秒(同样是在我的笔记本电脑上,已经使用了 3 年)。您真的需要更快的东西吗?请注意,父级在最后被删除。该解决方案的优点:
我发现您的实现是相关的,并将在以后记住它。您的选择应该基于您的场景:项目数量、缓存项目大小、命中率、依赖项数量……此外,保留太多数据会导致缓存速度通常很慢,并且会增加驱逐的可能性。
关于.net - 如何使 .NET MemoryCache 中的许多项目过期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19017760/
当您在 memcached 中设置 key 过期时,它实际上是在过期时被删除,还是在请求 key 时被删除(get)并且有效期已过。换句话说,过期会自动从 memcached 中删除值,还是简单地将其
Microsoft 是否已将客户端 secret 的有效期更改为最长 2 年?不能再选择“从不”了吗? 最佳答案 我自己也遇到了这个问题。您可以使用Powershell设置添加2年以上的凭据。所以我猜
我正在尝试对我网站上的 csv 文件强制禁止缓存。 我根据 apache 的文档将这些行添加到 httpd.conf: ExpiresActive On ExpiresDefault A0 Expi
我对 Cookie 不熟悉,希望让此 Cookie 在我的注销页面上过期 这是我设置 cookie 的位置: setcookie("loggood", "YES", $expire, "/",
MySQL 是否有某种功能可以在 x 秒后使特定行过期? 例如,我必须以下数据库: users id - integer name - string subscriptions
我的机器上安装了 Matlab Compiler Runtime。它工作正常,但现在当我运行一些需要它的代码时,我得到了这个错误: Failed to initialize MCR Instance:
当我从 PayPal 收到 IPN 时,我不想立即处理它,而是将消息排队,然后使用调度程序处理它。 因此,有一点让我担心 - 如果我将一条消息排队并只处理它(包括'_notify-validate'验
关于 PHP session 过期的问题。 如果该用户有一段时间不活动(出于测试目的,5 秒),我需要我的服务器丢弃 session 信息。 我看过this question尤其是 Gumbo(+28
我有一个 session ,在 30 分钟不活动后或 23.4 小时后被销毁。 我遇到的问题是无论事件如何, session 都会在 30 分钟后被销毁。因此,如果用户在 23.4 小时内一直处于事件
我一直在网上搜索并找到了许多奇怪的答案,而且我几乎尝试了所有这些答案。我的问题是这样的。我的登录页面包含: FormsAuthenticationTicket ticket = new FormsAu
我正在构建一个表单,我必须将数据存储在 HTML5 的 sessionStorage 中 我不知道 sessionStorage 何时过期。谁能告诉我 sessionStorage 的过期时间? 最佳
在我的应用程序中,我有一个必须始终有效的访问 token (Spotify 的)。当此访问 token 过期时,应用必须每 60 分钟刷新一次 token 端点并获取另一个访问 token 。 Aut
我们的办公室有一个简单的闭路电视系统,可以显示我们每个安全摄像头的实时图像。闭路电视系统没有 API 或任何提取实时图像的方法。但是,您可以通过创建带有图像链接的基本 HTML 页面从另一个浏览器查看
我正在基于DotNetOpenAuth实现OAuth2授权/资源服务器。我的服务器将发出生命周期很长的访问 token 。这些 token 将在iOS设备上使用。我看到的流程是这样的:1)要求用户在i
请帮助我在 Varnish 配置中添加过期 header 。 max_age 已在 vcl_fetch 中定义,需要根据 max_age 添加 expires header。 最佳答案 通常不需要设置
我正在开发一个必须使用 session 超时的应用程序。 问题是用户经常错过 session 超时并丢失数据。我已经在 javascript 中实现了一个小型 session 管理器,如果浏览器中有一
我有一个应用程序,可以从我的Instagram帐户中提取数据。 我曾经授权过此应用一次,并获得了访问 token 。但是我很担心 如果该 token 过期怎么办?我是否应该在每次 token 到期?
我在数据表中有多个复选框,它们具有一个名称和不同的值,我可以通过以下代码为所有选中的复选框存储 cookie $(document).ready(function(){ $('i
hibernate 3.3.x、ehcache 2.2.x The following error occurs, when I try to publish a lots of users in a
在 Azure 门户的通知中心的“配置”选项卡上,我能够生成主键和辅助键。我了解这些是获得对 Azure API 的编程访问权限所必需的 - 允许我的客户端应用程序创建注册并发送消息。 谁能解释一下:
我是一名优秀的程序员,十分优秀!