asp.net html5 缓存技术,ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core...

背景:

1:.NET Core 已经没System.Web,也木有了HttpRuntime.Cache,因此,该空间下Cache也木有了。

2:.NET Core 有新的Memory Cache提供,不过该内存类我看了一下,并没有支持文件的缓存依赖。

因此,在此前提下,预计.NET Core明年出来2.0版本时,可能也没支持文件的缓存依赖,因此,有必要提前准备实现。

在写此文前,我扫了一下园子里关于自定义缓存类的相关文章。

发现很多自定义的缓存类文章都简单停留在对字典的增删改查。

因此,决定补充这一篇完整思路的。

下面,就介绍一下这个缓存类的实现过程及原理。

实现缓存的类的核心思路介绍:

1:用static Dictionary 来存档。

A:为了处理并发,V4.0或以上,可以用System.Collections.Concurrent.ConcurrentDictionary 来存档。

B:如果为了支持.NET 2.0,则需要自己实现一个加锁的字典(本文即此种情况)

2:对该Dictionary提供增删改查方法。

3:提供定时缓存的过期策略。

4:提供文件监控策略。

5:测试并发、性能、和内存占用问题。

以下内容,重点介绍我的思路,源码截图以片断方式提供,具体的源码,会在链接中。

1:自定义线程安全的MDictionary(支持.NET 2.0)

如果要支持2.0,那么就只能自己实现了:实现的思路也很简单,只要对操作都加上锁即可:

8c7bfb4d9b3b007a2a877da4f91d4268.png

2:时间过期策略:

private MDictionary theCache = new MDictionary(2048, StringComparer.OrdinalIgnoreCase);//key,cache

private MDictionary theKeyTime = new MDictionary(2048, StringComparer.OrdinalIgnoreCase);//key,time

有了theKeyTime,在每取get cache的时候,根据时间可以判断出,该Key是不是,如果已过期,则放弃。

但是有一个问题,如果缓存已经过期,但一直不被调用,那不是一直存在?

为了解决这个问题,需要一个定时器,定时清理过期的Cache。

311a6e92d0c422406ceaaaa2a8353aaa.png

由于Cache已经被设计成单例,因此可以在构造函数启动一个线程,来做定时任务清理过期的缓存。

下面有两种策略,以前的,和现在的,我分别介绍一下:

以前的:

定时遍历theKeyTime,找到过期时间的Cache进行删除。

因为遍历期间集合不能修改或删除,因此将遍历的符合条件的存档到新的对象,再统一处理新的对象去清除。

优点:逻辑简单。

缺点:遍历的过程,缓存不能被修改,需要锁住(缓存的对象越多,锁住的时间越长),另外每次都要遍历所有。

现在的:

private SortedDictionary> theTime = new SortedDictionary>();//worktime,keylist

新增加了一个时间片字典,以固定的时间(如5分钟)为1个单位。

这样所有缓存的时间就有序的分散在这些时间片上,定时器只要按节奏处理一个就可以了。

每个时间片都记录所有的Key。

缺点:增加处理逻辑。

优点:过期策略不再有锁,能快速直接定位过期数据并清除。

3:关于List的性能

【一开始我的思路是List keys来存档所有key,移除的时候只移除key,然后其它交给定时器去清理。

由于只考虑它是线程安全,结果做性能测试时,很明显的发现问题】

List是链表实现,因此,随着数据量的增加,Contains方法的性能会极速下降。

因此,需要简单的处理一下解决性能问题,临时折腾了个MList:

internal class MList{

Listlist;

Dictionarydic;publicMList()

{

list= new List();

dic= new Dictionary();

}public MList(intnum)

{

list= new List(num);

dic= new Dictionary(num);

}public voidAdd(T key)

{

dic.Add(key,0);

list.Add(key);

}public boolContains(T key)

{returndic.ContainsKey(key);

}public voidRemove(T key)

{

dic.Remove(key);

list.Remove(key);

}public voidClear()

{

dic.Clear();

list.Clear();

}public intCount

{get{returnlist.Count;

}

}public ListGetList()

{returnlist;

}

}

4:文件缓存依赖策略:

这个简而言之,就是文件被修改的时候,如何使缓存自动过期。

我要支持这个策略的原因:是因为Taurus.MVC,对View加载的html会被缓存在内存中的,当html被修改时,需要及时反应清掉缓存并重新加载。

private MDictionary theFileName = new MDictionary();//key,filename

private MDictionary theFolderWatcher = new MDictionary();//folderPath,watch

private MDictionary> theFolderKeys = new MDictionary>();//folderPath,keylist

重点讲解:

1:用FileSystemWatcher来做文件监控(发现.NET Core里竟然有支持这个类)

2:问题:一开始,也是想的很简单,每一个文件开一个监控就完事了,结果没那么简单:

A:FileSystemWatcher对象太多,性能下降很快。

B:不同的Key指向同一个路径问题。

3:解决:后来,想到监控是以文件夹为单位,那么通过文件夹来搞搞实现:

A:以文件夹为单位:因此,文件对象即可以减少很多,提升性能问题。

B:以文件夹为单位:可以汇总对应的Keys,当文件变更时,可以快速定位到文件。

5:并发:

一个缓存类写好后,测试是少不了的,特别是并发,毕竟缓存是属于高并发的操作。

因此,缓存哪些地方要加lock的,哪些可以不加的,都需要仔细思考。

测试是通过的,就不截图了。

6:性能:

性能测试,是通过和HttpRuntime.Cache做的比较。

100万次的插入:

03bbafa150303082b13684f3b6e6010f.png

100万次的移除:

c74e92524386bc1de815e49191d2d699.png

7:占用内存:

暂无测试。

详细源码:

总结:

本来是计划昨天就写此文的,结果临时开了培训课,因此只能深夜来写此文了。

在培训的过程,大伙都问怎么提升技术?我答:造轮子。

另外,有人问我怎么看.NET Core,还能怎么看,拉好板凳,就等你了:.NET Core 2.0。

夜又深深,该入眠了~~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值