背景:

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

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

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

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

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

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

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

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

1:用static Dictionary<string,object> 来存档。

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

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

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

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

4:提供文件监控策略。

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

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

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

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

详情源码见:https://github.com/cyq1162/cyqdata/blob/master/Tool/MDictionary.cs

2:时间过期策略:

 private MDictionary<string, object> theCache = new MDictionary<string, object>(2048, StringComparer.OrdinalIgnoreCase);//key,cache
private MDictionary<string, DateTime> theKeyTime = new MDictionary<string, DateTime>(2048, StringComparer.OrdinalIgnoreCase);//key,time

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

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

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

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

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

以前的:

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

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

优点:逻辑简单。

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

现在的:

private SortedDictionary<int, MList<string>> theTime = new SortedDictionary<int, MList<string>>();//worktime,keylist

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

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

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

缺点:增加处理逻辑。

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

3:关于List的性能

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

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

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

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

 internal class MList<T>
{
List<T> list;
Dictionary<T, int> dic;
public MList()
{
list = new List<T>();
dic = new Dictionary<T, int>();
}
public MList(int num)
{
list = new List<T>(num);
dic = new Dictionary<T, int>(num);
}
public void Add(T key)
{
dic.Add(key, );
list.Add(key);
}
public bool Contains(T key)
{
return dic.ContainsKey(key);
}
public void Remove(T key)
{
dic.Remove(key);
list.Remove(key);
}
public void Clear()
{
dic.Clear();
list.Clear(); }
public int Count
{
get
{
return list.Count;
}
}
public List<T> GetList()
{
return list;
}
}

4:文件缓存依赖策略:

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

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

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

 private MDictionary<string, FileSystemWatcher> theFolderWatcher = new MDictionary<string, FileSystemWatcher>();//folderPath,watch
private MDictionary<string, MList<string>> theFolderKeys = new MDictionary<string, MList<string>>();//folderPath,keylist

重点讲解:

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

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

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

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

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

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

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

5:并发:

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

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

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

6:性能:

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

100万次的插入:

100万次的移除:

7:占用内存:

暂无测试。

详细源码:

https://github.com/cyq1162/cyqdata/blob/master/Cache/LocalCache.cs

总结:

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

关于培训见:http://www.cnblogs.com/cyq1162/p/6097445.html

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

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

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

ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core的更多相关文章

  1. C# 当前 .NET SDK 不支持将 .NET Core 2.1 设置为目标。请将 .NET Core 2.0 或更低版本设置为目标,或使用支持 .NET Core 2.1 的 .NET SDK 版本。

    报错信息: 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 NETSDK1045 当前 .NET SDK 不支持将 .NET Core 2.2 设置为目标.请将 .NET Core 2.1 或 ...

  2. ASP.NET Core 折腾笔记一

    前言: 在ASP.NET Core 1.0时,曾折腾过一次,后因发现不了System.Data而停止. 更因VS2015提示过期Delete掉VS了,其实主要还是笔记本的硬盘空间吃紧. 快双十一了,本 ...

  3. ASP.NET Core 2.2 : 二十一. 内容协商与自定义IActionResult和格式化类

    上一章的结尾留下了一个问题:同样是ObjectResult,在执行的时候又是如何被转换成string和JSON两种格式的呢? 本章来解答这个问题,这里涉及到一个名词:“内容协商”.除了这个,本章将通过 ...

  4. wr720n v4 折腾笔记(二):刷入不死Uboot

    0x01 前言 接着上节刷入Openwrt开始说起,此次开始刷入不死Uboot,刷入之后就可以在Uboot里面随便刷机,再也不怕成砖了. 固件附件地址: 下载地址1(还是之前一的包) flash文件地 ...

  5. ASP.NET HttpRuntime.Cache缓存类使用总结

    1.高性能文件缓存key-value存储—Redis 2.高性能文件缓存key-value存储—Memcached 备注:三篇博文结合阅读,简单理解并且使用,如果想深入学习,请多参考文章中给出的博文地 ...

  6. 当前 .NET SDK 不支持将 .NET Core 2.1 设置为目标。请将 .NET Core 2.0 或更低版本设置为目标,或使用支持 .NET Core 2.1 的 .NET SDK 版本。

    解决方案:项目>属性>应用程序>目标框架>安装其他框架. 此处我下载了2.1的x64的框架并安装. 安装后,重新打开vs即可点击切换新框架.

  7. 在CentOS7 开发与部署 asp.net core app笔记

    原文:在CentOS7 开发与部署 asp.net core app笔记 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/lihongzhai/art ...

  8. [转]ASP.NET Core 开发-Logging 使用NLog 写日志文件

    本文转自:http://www.cnblogs.com/Leo_wl/p/5561812.html ASP.NET Core 开发-Logging 使用NLog 写日志文件. NLog 可以适用于 . ...

  9. ASP.NET Core 开发-Logging 使用NLog 写日志文件

    ASP.NET Core 开发-Logging 使用NLog 写日志文件. NLog 可以适用于 .NET Core 和 ASP.NET Core . ASP.NET Core已经内置了日志支持,可以 ...

随机推荐

  1. MIP改造常见问题二十问

    在MIP推出后,我们收到了很多站长的疑问和顾虑.我们将所有疑问和顾虑归纳为以下二十个问题,希望对大家理解 MIP 有帮助. 1.MIP 化后对其他搜索引擎抓取收录以及 SEO 的影响如何? 答:在原页 ...

  2. 怎么让网站在本地支持SSL?

    打开vs,点击项目,查看属性,打开ssl 如果有什么危险提示,就允许 右击项目,选择属性 运行项目

  3. 网站定位之---根据IP获得区域

    记得以前做一个培训机构网站时候需要定位,那时候用的搜狐的api,不是很精准. demo:https://github.com/dunitian/LoTCodeBase/tree/master/NetC ...

  4. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

  5. 安卓易学,爬坑不易——腾讯老司机的RecyclerView局部刷新爬坑之路

    针对手游的性能优化,腾讯WeTest平台的Cube工具提供了基本所有相关指标的检测,为手游进行最高效和准确的测试服务,不断改善玩家的体验.目前功能还在免费开放中. 点击地址:http://wetest ...

  6. spring remoting源码分析--Hessian分析

    1. Caucho 1.1 概况 spring-remoting代码的情况如下: 本节近分析caucho模块. 1.2 分类 其中以hession为例,Hessian远程服务调用过程: Hessian ...

  7. Objective-C枚举的几种定义方式与使用

    假设我们需要表示网络连接状态,可以用下列枚举表示: enum CSConnectionState { CSConnectionStateDisconnected, CSConnectionStateC ...

  8. ORACLE分区表梳理系列(二)- 分区表日常维护及注意事项(红字需要留意)

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  9. A/B Testing的简要知识

    A/B testing主要用来检测网站或者APP的两个版本中哪一个更好,它的中心思想是把流量一分为二,一份用作experiment group,访问新的版本,另一份用作control group,访问 ...

  10. 亡命之徒aaaaaa.......chao

    前端是一个看似入门门槛不高,但要学好很难的领域.前端的知识体系庞杂又松散,技术演进快,如果摸不清脉络的话很容易陷入盲人摸象的困境甚至跑偏.其实只要掌握了正确的方法,学习前端和学好前端就只是个时间问题. ...