一个基于STSdb和fastJson的磁盘/内存缓存
一个基于STSdb和fastJson的磁盘/内存缓存
需求
业务系统用的是数据库,数据量大,部分只读或相对稳定业务查询复杂,每次页面加载都要花耗不少时间(不讨论异步),觉得可以做一下高速缓存,譬如用nosql那种key/value快速存取结果
目的
这里不是要做一个大家都适用的磁盘/内存缓存库,这个做法,部分是展示STSdb的用法,部分是提供一个简单易用的解决方案。
磁盘/内存
为什么不用memcached或者AppFabric Cache这样的现成解决方案呢?因为业务要缓存的内存或大或小,小的几KB,大的几MB,如果用户一多,势必对内存有过度的需求。所以选择做一个基于磁盘的。
当然,这个解决方案是支持内存缓存的。构造的时候传递空字符串便可。
STSdb是什么
再来说明一下STSdb是什么:STSdb是C#写的开源嵌入式数据库和虚拟文件系统,支持实时索引,性能是同类产品的几倍到几十倍,访问官方网站。
我之前介绍过:STSdb,最强纯C#开源NoSQL和虚拟文件系统 和 STSdb,最强纯C#开源NoSQL和虚拟文件系统 4.0 RC2 支持C/S架构 ,大家可以先看看。
实现
存取
因为是基于磁盘,所以需要使用到高效的Key/Value存取方案,碰巧我们有STSdb :)
序列化
因为要求简便快速,用的是fastJson。
代码
代码比较简单,花了2个小时写的,很多情况没考虑,譬如磁盘空间不足、过期空间回收等,这些留给大家做家庭作业吧。另外,为了发布方便,STSdb和fastJson的代码都合并到一个项目里。
CahceEngine.cs
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 bool isMemory = false; static CacheEngine() { memoryInstance = STSdb.FromMemory(); } 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) return memoryInstance; else return STSdb.FromFile(GetFile(false), GetFile(true)); } } public void Add<K>(string Category, K Key, object Data, DateTime? ExpirationDate) { var engine = Engine; var table = engine.OpenXIndex<K, string>(Category); var result = JSON.Instance.ToJSON(Data); table[Key] = result; table.Flush(); //add cache expiration time var expiration = engine.OpenXIndex<K, DateTime>(KeyExpiration); //default 30 mins before expiration var expirationDate = ExpirationDate == null || ExpirationDate <= DateTime.Now ? DateTime.Now.AddMinutes(30) : (DateTime)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 json; V result; if (table.TryGet(Key, out json)) { result = JSON.Instance.ToObject<V>(json); var expiration = engine.OpenXIndex<K, DateTime>(KeyExpiration); DateTime expirationDate; //verify expiration date if (expiration.TryGet(Key, out expirationDate)) { //expired if (expirationDate < DateTime.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; } }} |
新建
构造CacheEngine需要传递缓存保存到哪个文件夹。
基于内存
如果你不喜欢基于磁盘的缓存,可以使用基于内存,构造函数传递空字符串便可。
增加/更新
同一个方法: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 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 DateTime? Birthday { get; set; } } class Program { static void Main(string[] args) { TestAddGet(); //TestExpiration(); 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 TestAddGet() { var engine = new CacheEngine(@"..\..\data"); var f = new Foo { Name = "Wilson Chen", Age = 30, Birthday = DateTime.Now, Some = 123.456 }; engine.Add("User", "wchen", f, DateTime.Now.AddSeconds(10)); var t = @"Bla Bla Bla......"; engine.Add("PlainText", "Bla", t); var o = engine.Get<string, Foo>("User", "wchen"); Console.WriteLine(o.Name); var o4 = engine.Get<string, Foo>("User", "foo"); Console.WriteLine(o4 != null ? o4.Name : "foo does not exist"); var o2 = engine.Get<string, string>("PlainText", "Bla"); Console.WriteLine(o2); var o3 = engine.Get<string, string>("PlainText", "A"); Console.WriteLine(o3 ?? "A does not exist"); } }} |
说明
项目中引用了System.Management是因为STSdb支持内存数据库,需要判断最大物理内存。如果不喜欢,大家可以移除引用,并且去掉STSdb4.Database.STSdb.FromMemory方法便可。
下载
点击这里下载
一个基于STSdb和fastJson的磁盘/内存缓存的更多相关文章
- 基于STSdb和fastJson的磁盘/内存缓存
更新 1. 增加了对批量处理的支持,写操作速度提升5倍,读操作提升100倍 2. 增加了对并发的支持 需求 业务系统用的是数据库,数据量大,部分只读或相对稳定业务查询复杂,每次页面加载都要花耗不少时间 ...
- C#开源磁盘/内存缓存引擎
前言 昨天写了个 <基于STSdb和fastJson的磁盘/内存缓存>,大家可以先看看.下午用到业务系统时候,觉得可以改进一下,昨晚想了一个晚上,刚才重新实现一下. 更新 1. 增加了对批 ...
- 基于.net的通用内存缓存模型组件
谈到缓存,我们自然而然就会想到缓存的好处,比如: 降低高并发数据读取的系统压力:静态数据访问.动态数据访问 存储预处理数据,提升系统响应速度和TPS 降低高并发数据写入的系统压力 提升系统可用性,后台 ...
- 基于.net的分布式系统限流组件 C# DataGridView绑定List对象时,利用BindingList来实现增删查改 .net中ThreadPool与Task的认识总结 C# 排序技术研究与对比 基于.net的通用内存缓存模型组件 Scala学习笔记:重要语法特性
基于.net的分布式系统限流组件 在互联网应用中,流量洪峰是常有的事情.在应对流量洪峰时,通用的处理模式一般有排队.限流,这样可以非常直接有效的保护系统,防止系统被打爆.另外,通过限流技术手段,可 ...
- Memory Cache(内存缓存)
当Google测试了Google Search服务的可用性后,发现速度是最影响Web应用的可用性的因素之一.相对于作用相同但是速度慢的应用,用户更喜欢速度快的应用.多来年,Google已经掌握了如何使 ...
- Go/Python/Erlang编程语言对比分析及示例 基于RabbitMQ.Client组件实现RabbitMQ可复用的 ConnectionPool(连接池) 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil 分享基于MemoryCache(内存缓存)的缓存工具类,C# B/S 、C/S项目均可以使用!
Go/Python/Erlang编程语言对比分析及示例 本文主要是介绍Go,从语言对比分析的角度切入.之所以选择与Python.Erlang对比,是因为做为高级语言,它们语言特性上有较大的相似性, ...
- 关于实现一个基于文件持久化的EventStore的核心构思
大家知道enode框架的架构是基于ddd+event sourcing的思想.我们持久化的不是聚合根的最新状态,而是聚合根产生的领域事件.最近我在思考如何实现一个基于文件的eventstore.目标有 ...
- zabbix(一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案)
zabbix 是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定位/解决 ...
- 一个基于图的数据管理系统-gStore
gStore是遵循 BSD协议的一个开源项目.一个基于图的 RDF 三元组存储的数据管理系统.该项目是北京大学.滑铁卢大学.香港科技大学的联合研究项目.中国北京大学计算机科学与技术研究所的数据库组对该 ...
随机推荐
- C# 获取磁盘容量
原文:C# 获取磁盘容量 /// 获取指定驱动器的空间总大小(单位为B) /// </summary> /// <param name="str_HardDiskName& ...
- 【转】Oracle修改表空间为自动扩展
1.数据文件自动扩展的好处1)不会出现因为没有剩余空间可以利用到数据无法写入2)尽量减少人为的维护3)可以用于重要级别不是很大的数据库中,如测试数据库等 2.数据文件自动扩展的弊端1)如果任其扩大,在 ...
- HDOJ 4416 Good Article Good sentence
题解转自:http://blog.csdn.net/dyx404514/article/details/8807440 2012杭州网络赛的一道题,后缀数组后缀自己主动机都行吧. 题目大意:给一个字符 ...
- SQL点滴5—产生时间demention,主要是时间转换
原文:SQL点滴5-产生时间demention,主要是时间转换 数据仓库中有时间表,存储时间信息,这个存储过程接收开始时间结束时间,写入时间具体信息.有高手用excel函数功能很快能产生INSERT语 ...
- WIN7远程桌面重启、关机
在使用远程桌面访问Win7系统时会发现一个小问题,在xp远程桌面中存在的重启和关机菜单在win7远程桌面中不见了,如图: 这也给我们的使用带来了一些小小的麻烦,但实际上微软依然保留了命令行的方式来实现 ...
- three.js 源代码凝视(十六)Math/Frustum.js
商域无疆 (http://blog.csdn.net/omni360/) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:商域无疆 - 本博客专注于 敏捷开发 ...
- [原] 细说 NUMA
详说 NUMA 标签(空格分隔): Cloud2.0 测试条件 两台机器: CPU: Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz X 24 Intel(R) X ...
- Android项目---ActivityGroup的使用
ActivityGroup在一年前已经被说明不用了,但是腾讯QQ,新浪微博上也不乏ActivityGroup的身影.所以,即使是过时的东西,也有学习的必要,当然项目中也是可以添加的.在网上找了一个博客 ...
- NHProfiler使用方法
NHProfiler使用方法 NHProfiler是一个针对Nhibernate运行分析的工具. 使用如下: (1)在创建ISessionFactory的项目中引用NHProfiler安装目录下的Hi ...
- Android开发Tips-1
打算记录一些自己在开发过程中遇到的一些技巧性代码,方便以后遇到相似功能时能够快速的找到,那就从这里开始吧. 1,如何截取当前屏幕(不包括当前Activity的Title)并分享: a,获取当前Acti ...