[C#] 使用记忆体快取 MemoryCache 增加回应速度

在应用程序中有许多向资料库读取资料的动作,为了增加程序效能, 有 2 个方向可以调整。
第 1 种是直接调效 SQL 的效能,减少 SQL 的不良写法,让资料库查找资料的速度变快。
第 2 种是直接将上次查到的结果,先暂存在记忆体中,如果资料库的内容没有变动的话,直接回传刚刚已查过的资料内容,可以有效增加系统回应速度。

在 C# .Net 4.0 开始,我们可以善用 System.Runtime.Caching 的 MemoryCache 的快取机制来增加程序回应的速度。
记忆体内的存取速度远远比向资料库取资料快很多,而资料库取得的资料有时会因为网路限制而变更慢,所以在建置应用程序的时候,适时的加入记忆体快取机制在专案中可以有效增加效能。

什麽是 MemoryCache

MemoryCache 是实作记忆体内存取快取的方法。快取可以减少产生内容的工作,将已取得的资料暂存在记忆体空间,并指定暂存时间,可依时间到期而回收或是手动回收。
若应用程序重启时,原有存在快取的资料将会一并自动清除。此概念跟电脑的记忆体是相同的,存放在记忆体内的资料,当电脑重开机後也会一并自动清除。

范例1 指定时间後回收快取

此范例是说明读写快取的方法,而快取存活时间为 60 分钟後即立刻回收

ObjectCache Cache = MemoryCache.Default;

string CacheName = "Cache1";

// 检查快取是否存在
bool isSet = Cache[CacheName] != null;

// 取得资料库取得物件(省略动作)
DataTable dt = new DataTable();

// 写入快取 (指定时间後回收快取)
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(60); // 60 分钟後回收
Cache.Add(new CacheItem(CacheName, dt), policy);

// 读取快取
dt = (DataTable)Cache[CacheName];

// 移除快取
Cache.Remove(CacheName);

此范例讲解了存取 4 个主要动作,
1: 是否存在
2: 写入
3: 读取
4: 移除。
向记忆体存取需指定一个名称,Ex: Cache1,存取都需要用相同的名称。

范例中的 60 分钟是可以改变单位的,换成秒也是可以。
若要换成 60 秒的话,写法改成
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromSeconds (60); // 60 秒後回收

范例2 指定时间未使用时回收快取

此范例是讲解资料写入快取後,如果在 60 分钟内没有被读取时则会回收,若有被读取时,则会再延长 60 分钟

ObjectCache Cache = MemoryCache.Default;

string CacheName = "Cache2";

// 检查快取是否存在
bool isSet = Cache[CacheName] != null;

// 取得资料库取得物件(省略动作)
DataTable dt = new DataTable();

// 写入快取 (指定时间未使用时回收快取)
CacheItemPolicy policy = new CacheItemPolicy();
policy.SlidingExpiration = TimeSpan.FromMinutes(60); // 若 60 分钟内未呼叫此快取就会回收,若有呼叫则会再延长 60 分钟
Cache.Add(new CacheItem(CacheName, dt), policy);

// 读取快取
dt = (DataTable)Cache[CacheName];

// 移除快取
Cache.Remove(CacheName);

此范例跟第 1 个差异就是存活时间,如果这个快取有被使用则自动延长存活时间。
此两种范例都可以依实务上的需求而选择使用。
范例中的 60 分钟若要换成 60 秒的话,写法改成

policy.SlidingExpiration = TimeSpan. FromSeconds(60); // 60秒

自定常用方法类别

以上介绍了 2 种读写快取的方法,而快取还有另一种存活时间控制是 ChangeMonitors ,当有资料异动时就回收快取,但我没有实际上的应用,就没有实作范例了。

接下来我会展示我将快取常用的方法建立在 Class ,提供 4 个主要方法[ IsSet, Set, Get, Remove] 呼叫

public class AppCache
{
	#region 属性
	private ObjectCache Cache
	{
		get
		{
			return MemoryCache.Default;
		}
	}

	// 因为与其他应用程序共用此记忆体快取,所以建议增加此应用程序的前置名称
	private string IdNameStart = "MyProjectName_";
	#endregion

	#region 建构子
	public AppCache()
	{

	}
	#endregion


	#region 方法
	/// <summary>
	/// 取得快取
	/// </summary>
	/// <param name="key"></param>
	/// <returns></returns>
	public object Get(string key)
	{
		return Cache[IdNameStart + key];
	}

	/// <summary>
	/// 移除快取
	/// </summary>
	/// <param name="key"></param>
	public void Remove(string key)
	{
		Cache.Remove(IdNameStart + key);
	}

	/// <summary>
	/// 是否存在快取
	/// </summary>
	/// <param name="key"></param>
	/// <returns></returns>
	public bool IsSet(string key)
	{
		return (Cache[IdNameStart + key] != null);
	}

	/// <summary>
	/// 设定快取
	/// </summary>
	/// <param name="key">KEY</param>
	/// <param name="data">资料</param>
	public void Set(string key, object data)
	{
		this.Set(key, data, "Sliding", 60);
	}

	/// <summary>
	/// 设定快取
	/// </summary>
	/// <param name="key">KEY</param>
	/// <param name="data">资料</param>
	/// <param name="Expiration">保留别</param>
	/// <param name="cacheTime">保存时间(分钟)</param>
	public void Set(string key, object data, string Expiration, int cacheTime)
	{
		CacheItemPolicy policy = new CacheItemPolicy();
		if (Expiration == "Absolute")
		{
			policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
		}
		else if (Expiration == "Sliding")
		{
			policy.SlidingExpiration = TimeSpan.FromMinutes(cacheTime);
		}
		Cache.Add(new CacheItem(IdNameStart + key, data), policy);
	}
	#endregion
}

写好此类别,就可以方便使用。

使用的范例可以参考这个

AppCache cache = new AppCache();

// 检查Cache 是否存在
DataTable dt = null;
if (cache.IsSet("Cache1") == false)
{
	// 取得资料库取得物件(省略动作)
	dt = new DataTable();

	// 设定新 Cache , 60 分钟後就回收快取
	cache.Set("Cache1", dt, "Absolute", 60);
}
else
{
	// 取得 Cache 
	dt = (DataTable)cache.Get("Cache1");
}

// 移除 Cache 
cache.Remove("Cache1");

将常用的方法写入类别里,方便在应用程序中使用。

重点整理

  1. 使用 MemoryCache 是提高系统效能的方法之一
  2. 可在固定时间後回收 MemoryCache
  3. 可在未使用时回收 MemoryCache
  4. 整理好常用方法提供给各位

相关学习文章

[C#]QR Code 网址产生与解析 (附范例)
[C#] Base32 编码/解码方法 不分大小写的编码方式


<<:  可视化编程游戏引擎

>>:  Ruby幼幼班--Single Number

DAY 18 处理接收到的LINE emoji讯息-补充

这边改成只要在聊天室输入关键字就会传出LINE emoji讯息 前面处理LINE emoji讯息的函...

我的第一个RWD网页

开始之前先送上菜鸡的code 这是我第一次实作RWD的网页,又因为最近同步在看Bootstrap。 ...

Day35 参加职训(机器学习与资料分析工程师培训班),专题讨论

今日时间主要给学员与组员讨论专题,另外助教也分享参赛及制作专题的心得。 ...

Day13:13 - 购物车服务(1) - 後端 - 购物车总商品显示、加入购物车API

హలో,我是Charlie! 在Day12当中,我们完成了商品详情显示的API,而今天我们将完成後端...

[Day22]The 3n + 1 problem

上一篇介绍了Palindromes,上一题讲解了如何辨别是不是镜像字或是回文字的题目,只要先辨别出镜...