在我们开发的很多分布式项目里面(如基于WCF服务、Web API服务方式),由于数据提供涉及到数据库的相关操作,如果客户端的并发数量超过一定的数量,那么数据库的请求处理则以爆发式增长,如果数据库服务器无法快速处理这些并发请求,那么将会增加客户端的请求时间,严重者可能导致数据库服务或者应用服务直接瘫痪。缓存方案就是为这个而诞生,随着缓存的引入,可以把数据库的IO耗时操作,转换为内存数据的快速响应操作,或者把整个页面缓存到缓存系统里面。缓存框架在各个平台里面都有很多的实现,基本上多数是采用分布式缓存Redis、Memcached来实现。本系列文章介绍在.NET平台中,使用开源缓存框架CacheManager来实现数据的缓存的整个过程,本篇主要介绍CacheManager的使用和相关的测试。

1、CacheManager的介绍

CacheManager是一个以C#语言开发的开源.Net缓存框架抽象层。它不是具体的缓存实现,但它支持多种缓存提供者(如Redis、Memcached等)并提供很多高级特性。 CacheManager 主要的目的使开发者更容易处理各种复杂的缓存场景,使用CacheManager可以实现多层的缓存,让进程内缓存在分布式缓存之前,且仅需几行代码来处理。 CacheManager 不仅仅是一个接口去统一不同缓存提供者的编程模型,它使我们在一个项目里面改变缓存策略变得非常容易,同时也提供更多的特性:如缓存同步、并发更新、序列号、事件处理、性能计算等等,开发人员可以在需要的时候选择这些特性。

CacheManager的GitHub源码地址为:https://github.com/MichaCo/CacheManager,如果需要具体的Demo及说明,可以访问其官网:http://cachemanager.net/

使用Nuget为项目添加CacheManager包引用。CacheManager包含了很多的Package. 其中CacheManager.Core是必须的,其它的针对不同缓存平台上有不同的对应Package,整个Nuget包包含下面几个部分的内容。

CacheManager缓存框架支持Winform和Web等应用开发,以及支持多种流行的缓存实现,如MemoryCache、Redis、Memcached、Couchbase、System.Web.Caching等。

纵观整个缓存框架,它的特定很明显,在支持多种缓存实现外,本身主要是以内存缓存(进程内)为主,其他分布式缓存为辅的多层缓存架构方式,以达到快速命中和处理的机制,它们内部有相关的消息处理,使得即使是分布式缓存,也能够及时实现并发同步的缓存处理。

在网上充斥着基于某种单独缓存的实现和应用的趋势下,这种更抽象一层,以及提供更高级特性的缓存框架,在提供了统一编程模型的基础上,也实现了非常强大的兼容性,使得我一接触到这个框架,就对它爱不释手。

在GitHub上,缓存框架的前几名,除了这个缓存框架外,也还有一些,不过从文档的丰富程度等各方面来看,这个缓存框架还是非常值得拥有的。

CacheManager缓存框架在配置方面,支持代码方式的配置、XML配置,以及JSON格式的配置处理,非常方便。

CacheManager缓存框架默认对缓存数据的序列化是采用二进制方式,同时也支持多种自定义序列化的方式,如基于JOSN.NET的JSON序列化或者自定义序列化方式。

CacheManager缓存框架可以对缓存记录的增加、删除、更新等相关事件进行记录。

CacheManager缓存框架的缓存数据是强类型的,可以支持各种常规类型的处理,如Int、String、List类型等各种基础类型,以及可序列号的各种对象及列表对象。

CacheManager缓存框架支持多层的缓存实现,内部良好的机制可以高效、及时的同步好各层缓存的数据。

CacheManager缓存框架支持对各种操作的日志记录。

CacheManager缓存框架在分布式缓存实现中支持对更新的锁定和事务处理,让缓存保持更好的同步处理,内部机制实现版本冲突处理。

CacheManager缓存框架支持两种缓存过期的处理,如绝对时间的过期处理,以及固定时段的过期处理,是我们处理缓存过期更加方便。

....

很多特性基本上覆盖了缓存的常规特性,而且提供的接口基本上也是我们所经常用的Add、Put、Update、Remove等接口,使用起来也非常方便。

2、CacheManager缓存框架的应用

通过上面对CacheManager缓存框架的简单了解,我们大概了解了它应用的一些功能,但是实际上我们如何使用它,我们需要做一些学习和了解,首先我们需要在整个应用框架里面,知道缓存框架所扮演的角色。

一般来说,对于单机版本的应用场景,基本上是无需引入这种缓存框架的,因为客户端的并发量很少,而且数据请求也是寥寥可数的,性能方便不会有任何问题。

如果对于分布式的应用系统,如我在很多随笔中介绍到我的《混合式开发框架》、《Web开发框架》,由于数据请求是并发量随着用户增长而增长的,特别对于一些互联网的应用系统,极端情况下某个时间点一下可能就会达到了整个应用并发的峰值。那么这种分布式的系统架构,引入数据缓存来降低IO的并发数,把耗时请求转换为内存的高速请求,可以极大程度的降低系统宕机的风险。

我们以基于常规的Web API层来构建应用框架为例,整个数据缓存层,应该是在Web API层之下、业务实现层之上的一个层,如下所示。

在这个数据缓存层里面,我们引入了CacheManager缓存框架,实现分布式的缓存处理,使得我们的缓存数据能够在Redis服务器上实现数据的处理,同时可以在系统重启的时候,不至于丢失数据,能够快速恢复缓存数据。

为了实现对这个CacheManager缓存框架的使用,我们需要先进行一个使用测试,以便了解它的各个方便情况,然后才能广泛应用在我们的数据中间层上。

我们建立一个项目,并在引用的地方打开管理NuGet程序包,然后搜索到CacheManager的相关模块应用,并加入到项目引用里面,此为第一步工作。

我们创建一个客户对象类,用来模拟数据的存储和显示的,如下代码所示。

/// <summary>
/// 模拟数据存储的客户对象类
/// </summary>
public class Customer
{
private static Customer m_Customer = null;
private static ICacheManager<object> manager = null; //初始化列表值
private static List<string> list = new List<string>() { "123", "456", "789" }; /// <summary>
/// 客户对象的单件实例
/// </summary>
public static Customer Instance
{
get
{
if(m_Customer == null)
{
m_Customer = new Customer();
}
if (manager == null)
{
manager = CacheFactory.Build("getStartedCache", settings =>
{
settings.WithSystemRuntimeCacheHandle("handleName");
});
} return m_Customer;
}
}

这个类先做了一个单例的实现,并初始化缓存Customer类对象,以及缓存管理类ICacheManager<object> manager,这个是我们后面用来操作缓存数据的主要引用对象。

我们编写几个函数,用来实现对数据的获取,数据增加、数据删除的相关操作,并在数据增加、删除的时候,触发缓存的更新,这样我们下次获取数据的时候,就是最新的数据了。

/// <summary>
/// 获取所有客户信息
/// </summary>
/// <returns></returns>
public List<string> GetAll()
{
var value = manager.Get("GetAll") as List<string>;
if(value == null)
{
value = list;//初始化并加入缓存
manager.Add("GetAll", value); Debug.WriteLine("初始化并加入列表");
}
else
{
Debug.WriteLine("访问缓存获取:{0}", DateTime.Now);
}
return value;
} /// <summary>
/// 插入新的记录
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
public bool Insert(string customer)
{
//先获取全部记录,然后加入记录
if (!list.Contains(customer))
{
list.Add(customer);
} //重新设置缓存
manager.Update("GetAll", v => list);
return true;
} /// <summary>
/// 删除指定记录
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
public bool Delete(string customer)
{
if(list.Contains(customer))
{
list.Remove(customer);
}
manager.Update("GetAll", v=>list);
return true;
}

我们编写一个Winform程序来对这个缓存测试,以方便了解其中的机制。

我们在测试读取的时候,也就是对GetAll进行处理,插入以及删除主要就是为了测试缓存更新的处理。代码如下所示。

private void btnTestSimple_Click(object sender, EventArgs e)
{
var list = Customer.Instance.GetAll();
Debug.WriteLine("客户端获取记录数:{0}", list != null ? list.Count : 0);
} private void btnInsert_Click(object sender, EventArgs e)
{
var name = "abc";
Customer.Instance.Insert(name);
Debug.WriteLine(string.Format("插入记录:{0}", name));
} private void btnDelete_Click(object sender, EventArgs e)
{
var name = "abc";
Customer.Instance.Delete(name);
Debug.WriteLine(string.Format("删除记录:{0}", name));
}

我们跟踪记录,可以看到下面的日志信息。

我们可以看到,其中第一次是缓存没有的情况下进行初始化,初始化的记录数量为3个,然后插入记录后,再次获取数据的时候,缓存更新后的数量就变为4个了。

我们前面介绍了插入记录的后台代码,它同时进行了缓存数据的更新了。

/// <summary>
/// 插入新的记录
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
public bool Insert(string customer)
{
//先获取全部记录,然后加入记录
if (!list.Contains(customer))
{
list.Add(customer);
} //重新设置缓存
manager.Update("GetAll", v => list);
return true;
}

我们前面介绍的缓存初始化配置的时候,默认是使用内存缓存的,并没有使用分布式缓存的配置,它的初始化代码如下:

manager = CacheFactory.Build("getStartedCache", settings =>
{
settings.WithSystemRuntimeCacheHandle("handleName");
});

我们在正常情况下,还是需要使用这个强大的分布式缓存的,例如我们可以使用Redis的缓存处理,关于Redis的安装和使用,请参考我的随笔《基于C#的MongoDB数据库开发应用(4)--Redis的安装及使用》。

引入分布式的Redis缓存实现,我们的配置代码只需要做一定的改变即可,如下所示。

manager = CacheFactory.Build("getStartedCache", settings =>
{
settings.WithSystemRuntimeCacheHandle("handleName") .And
.WithRedisConfiguration("redis", config =>
{
config.WithAllowAdmin()
.WithDatabase(0)
.WithEndpoint("localhost", 6379);
})
.WithMaxRetries(100)
.WithRetryTimeout(50)
.WithRedisBackplane("redis")
.WithRedisCacheHandle("redis", true)
;
});

其他的使用没有任何变化,我们同时增加一些测试数据方便我们查阅对应的缓存数据。

/// <summary>
/// 测试加入几个不同的数据
/// </summary>
/// <returns></returns>
public void TestCache()
{
manager.Put("string", "abcdefg");
manager.Put("int", 2016);
manager.Put("decimal", 2016.9M);
manager.Put("date", DateTime.Now);
manager.Put("object", new UserInfo { ID = "123", Name = "Test", Age = 35 });
}
private void btnTestSimple_Click(object sender, EventArgs e)
{
var list = Customer.Instance.GetAll();
Debug.WriteLine("客户端获取记录数:{0}", list != null ? list.Count : 0); //测试加入一些值
Customer.Instance.TestCache();
}

我们其中测试,一切和原来没有什么差异,程序的记录信息正常。

但是我们配置使用了Redis的缓存处理,因此可以使用“Redis Desktop Manager”软件来查看对应的缓存数据的,打开软件我们可以看到对应的缓存记录如下所示。

从上图我们可以查看到,我们添加的所有缓存键值都可以通过这个Redis的客户来进行查看,因为我们缓存里面有基于Redis缓存的实现,同理如果我们配置其他的缓存实现,如MemCache等,那么也可以在对应的管理界面上查看到。

我们完成这些处理后,可以发现缓存数据是可以实现多层缓存的,最为高效的就是内存缓存(也是它的主缓存),它会自动协同好各个分布式缓存的数据版本冲突问题。

引入如Redis的分布式缓存有一个好处,就是我们的数据可以在程序重新启动的时候,如果没有在内存缓存里面找到(没有击中目标),那么会寻找分布式缓存并进行加载,从而即使程序重启,我们之前的缓存数据依旧保存完好。

以上就是我基于对缓存框架的整体了解和其角色扮演做的相关介绍,以及介绍CacheManager的使用和一些场景的说明,通过上面简单案例的研究,我们可以逐步引入到更具实际价值的Web API 框架层面上进行使用,以期把缓存框架发挥其真正强大的价值,同时也为我们各种不同的缓存需要进行更高层次的探索,希望大家继续支持。

出自:http://www.cnblogs.com/wuhuacong/p/5889305.html

.NET缓存框架CacheManager---1、CacheManager的介绍的更多相关文章

  1. C#开发微信门户及应用(48) - 在微信框架中整合CacheManager 缓存框架

    在我们的很多框架或者项目应用中,缓存在一定程度上可以提高程序的响应速度,以及减轻服务器的承载压力,因此在一些地方我们都考虑引入缓存模块,这篇随笔介绍使用开源缓存框架CacheManager来实现数据的 ...

  2. .NET缓存框架CacheManager在混合式开发框架中的应用(1)-CacheManager的介绍和使用

    在我们开发的很多分布式项目里面(如基于WCF服务.Web API服务方式),由于数据提供涉及到数据库的相关操作,如果客户端的并发数量超过一定的数量,那么数据库的请求处理则以爆发式增长,如果数据库服务器 ...

  3. NET缓存框架CacheManager在混合式开发框架中的应用(1)-CacheManager的介绍和使用

    在我们开发的很多分布式项目里面(如基于WCF服务.Web API服务方式),由于数据提供涉及到数据库的相关操作,如果客户端的并发数量超过一定的数量,那么数据库的请求处理则以爆发式增长,如果数据库服务器 ...

  4. 在.NET项目中使用PostSharp,使用CacheManager实现多种缓存框架的处理

    在前面几篇随笔中,介绍了PostSharp的使用,以及整合MemoryCache,<在.NET项目中使用PostSharp,实现AOP面向切面编程处理>.<在.NET项目中使用Pos ...

  5. OSCache缓存框架介绍

          OSCache是一种开放性的JSP定制标记应用,由OpenSymphony设计,提供了在现有JSP页面之内实现快速内存缓冲的功能. OSCache是个一个广泛采用的高性能的J2EE缓存框架 ...

  6. SpringMVC集成缓存框架Ehcache

    在互联网应用中,应用并发比传统企业及应用会高出很多.解决并发的根本在于系统的响应时间与单位时间的吞吐量.思路可分为:一减少系统的不必要开支(如缓存),二是提高系统单位时间内的运算效率(如集群). 在硬 ...

  7. 缓存框架Ehcache相关

    单点缓存框架   只能针对单个jvm中,缓存容器存放jvm中,每个缓存互不影响  Ehcache gauva chache 内置缓存框架 jvm缓存框架 分布式缓存框架(共享缓存数据)  Redis ...

  8. [原创]mybatis中整合ehcache缓存框架的使用

    mybatis整合ehcache缓存框架的使用 mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓 ...

  9. Spring4.1新特性——Spring缓存框架增强(转)

    目录 Spring4.1新特性——综述 Spring4.1新特性——Spring核心部分及其他 Spring4.1新特性——Spring缓存框架增强 Spring4.1新特性——异步调用和事件机制的异 ...

随机推荐

  1. POJ 2485 Highways (prim最小生成树)

    对于终于生成的最小生成树中最长边所连接的两点来说 不存在更短的边使得该两点以不论什么方式联通 对于本题来说 最小生成树中的最长边的边长就是使整个图联通的最长边的边长 由此可知仅仅要对给出城市所抽象出的 ...

  2. 模板引擎mustache.js

    Javascript模板引擎mustache.js详解   阅读目录 1. 从一个简单真实的需求讲起 2. mustache的用法 3. mustache的思想 4. {{prop}}标签 5. {{ ...

  3. Xamarin.Android 在VS下调试时提示 In mgmain JNI_OnLoad 程序“Mono”已退出 解决办法

    原因是使用了破解版的 Xamarin,调试时不能使用共享库

  4. UVa 524 Prime Ring Problem(DFS , 回溯)

    题意  把1到n这n个数以1为首位围成一圈  输出全部满足随意相邻两数之和均为素数的全部排列 直接枚举排列看是否符合肯定会超时的  n最大为16  利用回溯法 边生成边推断  就要快非常多了 #inc ...

  5. Partition List -- LeetCode

    原题链接: http://oj.leetcode.com/problems/partition-list/  这是一道链表操作的题目,要求把小于x的元素按顺序放到链表前面.我们仍然是使用链表最经常使用 ...

  6. HTML5实际和离线应用分析

    当前离线Web申请书,即,该装置不能访问因特网时的应用的执行.HTML5离线应用重点,主要开发人员希望.步骤离线应用开发有:首先我们应该知道设备是否可以连接;然后,它也应该可以访问某些资源(像.CSS ...

  7. win7开机直接进入系统系统桌面

    在开始搜索栏输入:netplwiz   选中admin用户(也就是你登录的用户名),然后在把上面的勾去掉,点应用,会提示输入用户名和密码,输二次,是一样的密码,如果没设密码,就不用输直接应用,确定就O ...

  8. 【Android进阶】快捷图标的创建与移除

    注释已经说得很清楚了,如果有疑问,请留言 /** * 添加桌面快捷方式 * * @param view */ public void click1(View view) { if (isExit()) ...

  9. 【Java基础】“数三退一”问题的代码实现

    现在有500个小孩,编号为0-499,手牵手连成一个圈,从第一个小孩开始"123123..."报数,数到三的小孩退出,求剩下的最后一个小孩的编号. public static vo ...

  10. JVM学习(1)——通过实例总结Java虚拟机的运行机制(转)

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms ...