大佬教程收集整理的这篇文章主要介绍了基于STSdb和fastJson的磁盘/内存缓存,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
业务系统用的是数据库,数据量大,部分只读或相对稳定业务查询复杂,每次页面加载都要花耗不少时间(不讨论异步),觉得可以做一下高速缓存,譬如用nosql那种Key/value快速存取结果
@H_874_6@目的
这里不是要做一个大家都适用的磁盘/内存缓存库,这个做法,部分是展示STSdb的用法,部分是提供一个简单易用的解决方案。
为什么不用memcached或者AppFabric Cache这样的现成解决方案呢?因为业务要缓存的内存或大或小,小的几KB,大的几MB,如果用户一多,势必对内存有过度的需求。所以选择做一个基于磁盘的。
当然,这个解决方案是支持内存缓存的。构造的时候传递空字符串便可。
STSdb是什么
再来说明一下STSdb是什么:STSdb是C#写的开源嵌入式数据库和虚拟文件系统,支持实时索引,性能是同类产品的几倍到几十倍,访问官方网站。
我之前介绍过:STSdb,最强纯C#开源NoSQL和虚拟文件系统和STSdb,最强纯C#开源NoSQL和虚拟文件系统 4.0 RC2 支持C/S架构,大家可以先看看。
因为是基于磁盘,所以需要使用到高效的Key/value存取方案,碰巧我们有STSdb :)
代码比较简单,花了2个小时写的,很多情况没考虑,譬如磁盘空间不足、过期空间回收等,这些留给大家做家庭作业吧。另外,为了发布方便,STSdb和fastJson的代码都合并到一个项目里。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using STSdb4.Database; using fastJSON; using System.IO; namespace Com.SuperCache.ENGIne { public class CacheENGIne { private const String KeyExpiration = "Expiration"; private String dataPath; private static IStorageENGIne memoryInstance = null; private static object syncRoot = new object(); private bool isMemory = false; public CacheENGIne(String DataPath) { dataPath = DataPath; if (!dataPath.EndsWith(Path.DirectorySeparatorChar.ToString())) dataPath += Path.DirectorySeparatorChar; isMemory = String.IsNullOrEmpty(DataPath); } public void Add<K>(String Category,K Key,object Data) { Add(Category,Key,Data,null); } private IStorageENGIne ENGIne { get { if (isMemory) { lock (syncRoot) { if (memoryInstance == null) memoryInstance = STSdb.FromMemory(); } return memoryInstance; } else return STSdb.FromFile(GetFile(false),GetFile(true)); } } public void Add<K>(String Category,object Data,datetiR_861_11845@e? ExpirationDatE) { var ENGIne = ENGIne; var table = ENGIne.openXIndex<K,String>(Category); var result = Data is String ? (String)Data : JSON.Instance.ToJSON(Data); table[Key] = result; table.Flush(); var expiration = ENGIne.openXIndex<K,datetiR_861_11845@e>(KeyExpiration); var expirationDate = ExpirationDate == null || ExpirationDate <= datetiR_861_11845@e.Now ? datetiR_861_11845@e.Now.Addminutes(30) : (datetiR_861_11845@E)ExpirationDate; expiration[Key] = expirationDate; expiration.Flush(); ENGIne.Commit(); if (!isMemory) ENGIne.Dispose(); } private String GetFile(bool IsData) { if (!Directory.Exists(dataPath)) Directory.CreateDirectory(dataPath); return dataPath + "SuperCache." + (IsData ? "dat" : "sys"); } public V Get<K,V>(String Category,K Key) { var ENGIne = ENGIne; var table = ENGIne.openXIndex<K,String>(Category); String buffer; V result; if (table.TryGet(Key,out buffer)) { result = typeof(V) == typeof(String) ? (V)(object)buffer : JSON.Instance.ToObject<V>(buffer); var expiration = ENGIne.openXIndex<K,datetiR_861_11845@e>(KeyExpiration); datetiR_861_11845@e expirationDate; if (expiration.TryGet(Key,out expirationDatE)) { if (expirationDate < datetiR_861_11845@e.Now) { result = default(V); table.delete(Key); table.Flush(); expiration.delete(Key); expiration.Flush(); ENGIne.Commit(); } } } else result = default(V); if (!isMemory) ENGIne.Dispose(); return result; } } }
如果你不喜欢基于磁盘的缓存,可以使用基于内存,构造函数传递空字符串便可。
同一个方法:Add。用户可以指定类型(Category),譬如User,employee等。键(Key)支持泛型,值(Data)是object。有一个overload是过期日期(Expirationdate),默认当前时间30分钟后
Get方法需要指定类型(Category)和键(Key)。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using Com.SuperCache.ENGIne; namespace Com.SuperCache.Test { public class Foo { public String Name { get; set; } public int age { get; set; } public double? Some { get; set; } public datetiR_861_11845@e? Birthday { get; set; } } class Program { static void Main(String[] args) { TestAddGet(); //TestExpiration(); TestPerfoRMANce(); Console.Read(); } private static void TestExpiration() { var ENGIne = new CacheENGIne(@"..\..\data"); var o = ENGIne.Get<String,Foo>("User","wchen"); Console.WriteLine(o != null ? o.Name : "wchen does not exist or expired"); } private static void TestPerfoRMANce() { var ENGIne = new CacheENGIne(@"..\..\data"); var w = new Stopwatch(); w.Start(); for (int i = 0; i < 100; i++) { var o2 = ENGIne.Get<String,String>("Plaintext","Bla"); } w.Stop(); Console.WriteLine(w.Elapsed); } private static void TestAddGet() { var ENGIne = new CacheENGIne(@"..\..\data"); var f = new Foo { Name = "Wilson Chen",Age = 30,Birthday = datetiR_861_11845@e.Now,Some = 123.456 }; ENGIne.Add("User","wchen",f,datetiR_861_11845@e.Now.AddSeconds(10)); var t = @"Bla Bla Bla......"; ENGIne.Add("Plaintext","Bla",t); var o = ENGIne.Get<String,"wchen"); var o4 = ENGIne.Get<String,"foo"); Console.WriteLine(o4 != null ? o4.Name : "foo does not exist"); var o2 = ENGIne.Get<String,"Bla"); Console.WriteLine(o.Name); var o3 = ENGIne.Get<String,"A"); Console.WriteLine(o3 ?? "A does not exist"); } } }
项目中引用了System.Management是因为STSdb支持内存数据库,需要判断最大物理内存。如果不喜欢,大家可以移除引用,并且去掉STSdb4.Database.STSdb.FromMemory方法便可。
点击这里下载
以上是大佬教程为你收集整理的基于STSdb和fastJson的磁盘/内存缓存全部内容,希望文章能够帮你解决基于STSdb和fastJson的磁盘/内存缓存所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。