最近有个需求需要定时清理服务器上所有的缓存。本来以为很简单的调用一下 MemoryCache.Clear 方法就完事了。谁知道 MemoryCache 类以及 IMemoryCache 扩展方法都没有 Clear 方法。这可给难住了,于是想找到所有的 Keys 来一个个 Remove ,谁知道居然也没有获取所有 Key 的方法。于是研究了一下 ,找到一些方法,下面介绍两个方法:

自定义 CacheWrapper 包装类

MemoryCache 构造 Entry 的时候支持传入 CancellationChangeToken 对象,当 CancellationChangeToken.Cancel 触发的时候会自动使该对象过期。那么我们只要对 MemoryCache 类包装一下很容易实现一个自己的 Cache 类。

 public class CacheWrapper
{
private readonly IMemoryCache _memoryCache;
private CancellationTokenSource _resetCacheToken = new(); public CacheWrapper(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
} public void Add(object key, object value, MemoryCacheEntryOptions memoryCacheEntryOptions)
{
using var entry = _memoryCache.CreateEntry(key);
entry.SetOptions(memoryCacheEntryOptions);
entry.Value = value; // add an expiration token that allows us to clear the entire cache with a single method call
entry.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));
} public object Get(object key)
{
return _memoryCache.Get(key);
} public void Remove(object key)
{
_memoryCache.Remove(key);
} public void Clear()
{
_resetCacheToken.Cancel(); // this triggers the CancellationChangeToken to expire every item from cache _resetCacheToken.Dispose(); // dispose the current cancellation token source and create a new one
_resetCacheToken = new CancellationTokenSource();
}
}

然后单元测试测试一下:


[TestMethod()]
public void ClearTest()
{
var memCache = new MemoryCache(new MemoryCacheOptions());
var wrapper = new CacheWrapper(memCache); for (int i = 0; i < 10; i++)
{
wrapper.Add(i.ToString(), new object(), new MemoryCacheEntryOptions());
} Assert.IsNotNull(wrapper.Get("1"));
Assert.IsNotNull(wrapper.Get("9")); wrapper.Clear(); for (int i = 0; i < 10; i++)
{
Assert.IsNull(wrapper.Get(i.ToString()));
} for (int i = 0; i < 10; i++)
{
wrapper.Add(i.ToString(), new object(), new MemoryCacheEntryOptions());
} Assert.IsNotNull(wrapper.Get("1"));
Assert.IsNotNull(wrapper.Get("9")); wrapper.Clear(); for (int i = 0; i < 10; i++)
{
Assert.IsNull(wrapper.Get(i.ToString()));
} }

测试通过。

Compact 方法

以上 CacheWrapper 类虽然可以实现我们想要的功能,但是对于原来的程序有侵入,需要使用 CacheWrapper 类替换默认的 MemoryCache 类,不是太好。于是不死心继续研究,后来直接看了 MemoryCache 的代码(源码在这),开源真香。发现 MemoryCache 有个 Compact 方法好像在干删除的勾当。也怪我英文不好,这单词是压缩的意思,居然才发现。。。。于是我们的清除所有对象的需求不就轻而易举了么?

 /// Remove at least the given percentage (0.10 for 10%) of the total entries (or estimated memory?), according to the following policy:
/// 1. Remove all expired items.
/// 2. Bucket by CacheItemPriority.
/// 3. Least recently used objects.
/// ?. Items with the soonest absolute expiration.
/// ?. Items with the soonest sliding expiration.
/// ?. Larger objects - estimated by object graph size, inaccurate.
MemoryCache.Compact(double percentage);

Compact 方法会对缓存的对象进行压缩,参数是个double,0.1 表示压缩 10% ,那么传 1.0 就是压缩 100%,那不就是 Clear All 么。所以我可以使用 Compact(1.0) 来清除所有的缓存对象。单元测试跑一下:

[TestMethod()]
public void CompactTest()
{
var memCache = new MemoryCache(new MemoryCacheOptions()); for (int i = 0; i < 10; i++)
{
memCache.Set(i.ToString(), new object(), new MemoryCacheEntryOptions());
} Assert.IsNotNull(memCache.Get("1"));
Assert.IsNotNull(memCache.Get("9")); memCache.Compact(1); for (int i = 0; i < 10; i++)
{
Assert.IsNull(memCache.Get(i.ToString()));
} for (int i = 0; i < 10; i++)
{
memCache.Set(i.ToString(), new object(), new MemoryCacheEntryOptions());
} Assert.IsNotNull(memCache.Get("1"));
Assert.IsNotNull(memCache.Get("9")); memCache.Compact(1); for (int i = 0; i < 10; i++)
{
Assert.IsNull(memCache.Get(i.ToString()));
}
}

完美通过。

这里简单介绍下 Compact 方法。根据注释它会按照已下优先级删除对象:

  1. 过期的对象
  2. CacheItemPriority 设置的优先级,等级越高越不容易被删除
  3. 最近最少被使用的对象
  4. 绝对过期时间
  5. 滑动过期时间
  6. 大对象

关注我的公众号一起玩转技术



MemoryCache 如何清除全部缓存?的更多相关文章

  1. Android手机清除微信缓存

    方法一: 1.任意找一个微信好友,给他发送网址 http://debugx5.qq.com 2.自己点击这个网址跳转 3.进入后看到下面的页面,通过勾选第二张截图的Cookie和文件缓存来清除微信缓存 ...

  2. 关于清除arp 缓存的那点事儿

    在Linux下,清除arp缓存表,例如: arp -d 10.0.3.6 我们可以用上面这条命令清除某一条记录,也可以用 arp -n |awk '/^[1-9]/{print "arp - ...

  3. iOS //清除本地缓存

    //清除本地缓存 -(void)clearCache{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT ...

  4. Chrome清除dns缓存

    Chrome清除dns缓存 为了加快访问速度,Google Chrome浏览器采用了预提DNS记录,在本地建立DNS缓存的方法,加快网站的连接速度.你在谷歌Chrome浏览器的地址栏中输入about: ...

  5. SDWebImage清除图片缓存

    背景: 使用 SDWebImage 库,由于内存中一直缓存着加载的图片,而导致内存过高(我们无法手动管理内存),弹出内存警告而导致程序很卡或者直接crash掉. 我的解决方法: 在AppDelegat ...

  6. js清除浏览器缓存的几种方法

    2014年9月24日 4692次浏览 关于浏览器缓存 浏览器缓存,有时候我们需要他,因为他可以提高网站性能和浏览器速度,提高网站性能.但是有时候我们又不得不清除缓存,因为缓存可能误事,出现一些错误的数 ...

  7. 清除dns缓存

    Linux清除dns缓存命令 /etc/init.d/dnsmasq restart

  8. 如何清除DNS缓存,使用cmd命令清理DNS缓存方法

    如何清除DNS缓存,使用cmd命令清理DNS缓存方法 有时候电脑突然上不了网,或者存在某些网站打不开的情况,但别的网站又可以打开,解决办法需要清除DNS缓存,那么如何清除DNS缓存呢,最常用的方法就是 ...

  9. jquery是如何清除ajax缓存的

    大家都知道万恶的IE在ajax中往往只读取第一次ajax请求时候的数据,其余时候都是从cache提取数据,(太懒了T_T).原生的JS清除ajax缓存的方法多,但是终觉有点繁琐,如果是用jquery的 ...

随机推荐

  1. [bzoj5294]二进制

    首先可以发现$2^k$模3意义下有循环节,也就是1,-1,1,-1--考虑对于x个1,y个0,判断是否存在3的倍数1.x为偶数时一定可以,选择等量的1和-1即可2.x为奇数,要满足$x\ge 3$且$ ...

  2. Git操作: git commit代码后,如何撤回且保留commit的代码

    git commit代码后,但是没有push之前,如果发现提交的代码有一个部分是有问题的,或者commit message写的太随便了想改一下,以下命令会帮到你 git reset HEAD^ 敲击该 ...

  3. ICCV2021 | SOTR:使用transformer分割物体

    ​前言 本文介绍了现有实例分割方法的一些缺陷,以及transformer用于实例分割的困难,提出了一个基于transformer的高质量实例分割模型SOTR. 经实验表明,SOTR不仅为实例分割提供了 ...

  4. Java二次开发海康SDK-对接门禁机

    写在最前 SDK版本:CH-HCNetSDKV6.1.6.45_build20210302_win64 参考文档:海康SDK使用手册_V6.1 对接测试设备型号:DS-K1T671M 设备序列号:E5 ...

  5. 监听浏览器tab切换

    监听浏览器切屏 为了完成验证用户在切换浏览器tab时进行登录再次认证需求需要监听浏览器切换窗口 if (document.hidden !== undefined) { document.addEve ...

  6. SQLite3 约束和简单命令

    安装sqlite3,配置环境变量. 1.打开数据库 sqlite3.exe db_name.db 2.常用命令 .tables 查看所有表 .headers on 设置显示表头 .schema tab ...

  7. Matlab指针

    Matlab指针 第一印象貌似是Matlab中不存在指针,所有变量与函数的赋值都是按值传递的,不会对参数进行修改.其实Matlab提供了handle类作为指针代替品.只要我们利用handle子类,就可 ...

  8. 毕业设计之dns搭建:

    [apps@dns_sever ~]$ sudo yum install -y bind [apps@dns_sever ~]$ sudo vim /etc/named.conf // // name ...

  9. Redis——面试官考题

    总结: 本文在一次面试的过程中讲述了 Redis 是什么,Redis 的特点和功能,Redis 缓存的使用,Redis 为什么能这么快,Redis 缓存的淘汰策略,持久化的两种方式,Redis 高可用 ...

  10. Hi3516开发笔记(六):通过HiTools使用USB/串口将uboot、kernel、roofts和userdata按照分区表烧写镜像

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/121706033红胖子(红模仿)的博文大全:开发技术集合( ...