zoukankan      html  css  js  c++  java
  • 基于STSdb和fastJson的磁盘/内存缓存

    http://blog.csdn.net/dyllove98/article/details/9238415

    基于STSdb和fastJson的磁盘/内存缓存

     78人阅读 评论(0) 收藏 举报
     

    目录(?)[+]

     

    需求

    业务系统用的是数据库,数据量大,部分只读或相对稳定业务查询复杂,每次页面加载都要花耗不少时间(不讨论异步),觉得可以做一下高速缓存,譬如用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

    [csharp] view plaincopyprint?
     
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5. using STSdb4.Database;  
    6. using fastJSON;  
    7. using System.IO;  
    8.   
    9. namespace Com.SuperCache.Engine  
    10. {  
    11.     public class CacheEngine  
    12.     {  
    13.         private const string KeyExpiration = "Expiration";  
    14.         private string dataPath;  
    15.         private static IStorageEngine memoryInstance = null;  
    16.         private static object syncRoot = new object();  
    17.         private bool isMemory = false;  
    18.   
    19.         public CacheEngine(string DataPath)  
    20.         {  
    21.             dataPath = DataPath;  
    22.             if (!dataPath.EndsWith(Path.DirectorySeparatorChar.ToString()))  
    23.                 dataPath += Path.DirectorySeparatorChar;  
    24.   
    25.             isMemory = string.IsNullOrEmpty(DataPath);  
    26.         }  
    27.   
    28.         public void Add<K>(string Category, K Key, object Data)  
    29.         {  
    30.             Add(Category, Key, Data, null);  
    31.         }  
    32.   
    33.         private IStorageEngine Engine  
    34.         {  
    35.             get  
    36.             {  
    37.                 if (isMemory)  
    38.                 {  
    39.                     lock (syncRoot)  
    40.                     {  
    41.                         if (memoryInstance == null)  
    42.                             memoryInstance = STSdb.FromMemory();  
    43.                     }  
    44.                     return memoryInstance;  
    45.                 }  
    46.                 else  
    47.                     return STSdb.FromFile(GetFile(false), GetFile(true));  
    48.             }  
    49.         }  
    50.   
    51.         public void Add<K>(string Category, K Key, object Data, DateTime? ExpirationDate)  
    52.         {  
    53.             var engine = Engine;  
    54.             var table = engine.OpenXIndex<K, string>(Category);  
    55.             var result = Data is string ? (string)Data : JSON.Instance.ToJSON(Data);  
    56.             table[Key] = result;  
    57.             table.Flush();  
    58.   
    59.             var expiration = engine.OpenXIndex<K, DateTime>(KeyExpiration);  
    60.             var expirationDate = ExpirationDate == null || ExpirationDate <= DateTime.Now ? DateTime.Now.AddMinutes(30) : (DateTime)ExpirationDate;  
    61.             expiration[Key] = expirationDate;  
    62.             expiration.Flush();  
    63.   
    64.             engine.Commit();  
    65.   
    66.             if (!isMemory)  
    67.                 engine.Dispose();  
    68.         }  
    69.   
    70.         private string GetFile(bool IsData)  
    71.         {  
    72.             if (!Directory.Exists(dataPath))  
    73.                 Directory.CreateDirectory(dataPath);  
    74.             return dataPath + "SuperCache." + (IsData ? "dat" : "sys");  
    75.         }  
    76.   
    77.         public V Get<K, V>(string Category, K Key)  
    78.         {  
    79.             var engine = Engine;  
    80.             var table = engine.OpenXIndex<K, string>(Category);  
    81.             string buffer;  
    82.             V result;  
    83.             if (table.TryGet(Key, out buffer))  
    84.             {  
    85.                 result = typeof(V) == typeof(string) ? (V)(object)buffer : JSON.Instance.ToObject<V>(buffer);  
    86.                 var expiration = engine.OpenXIndex<K, DateTime>(KeyExpiration);  
    87.                 DateTime expirationDate;  
    88.                 if (expiration.TryGet(Key, out expirationDate))  
    89.                 {  
    90.                     if (expirationDate < DateTime.Now)  
    91.                     {  
    92.                         result = default(V);  
    93.                         table.Delete(Key);  
    94.                         table.Flush();  
    95.                         expiration.Delete(Key);  
    96.                         expiration.Flush();  
    97.                         engine.Commit();  
    98.                     }  
    99.                 }  
    100.             }  
    101.             else  
    102.                 result = default(V);  
    103.   
    104.             if (!isMemory)  
    105.                 engine.Dispose();  
    106.   
    107.             return result;  
    108.         }  
    109.     }  
    110. }  

    新建

    构造CacheEngine需要传递缓存保存到哪个文件夹。

    基于内存

    如果你不喜欢基于磁盘的缓存,可以使用基于内存,构造函数传递空字符串便可。

    增加/更新

    同一个方法:Add。用户可以指定类型(Category),譬如User,Employee等。键(Key)支持泛型,值(Data)是object。有一个overload是过期日期(ExpirationDate),默认当前时间30分钟后

    获取

    Get方法需要指定类型(Category)和键(Key)。

     

    例子

    [csharp] view plaincopyprint?
     
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5. using System.Diagnostics;  
    6. using Com.SuperCache.Engine;  
    7.   
    8. namespace Com.SuperCache.Test  
    9. {  
    10.     public class Foo  
    11.     {  
    12.         public string Name { getset; }  
    13.         public int Age { getset; }  
    14.         public double? Some { getset; }  
    15.         public DateTime? Birthday { getset; }  
    16.     }  
    17.   
    18.     class Program  
    19.     {  
    20.         static void Main(string[] args)  
    21.         {  
    22.             TestAddGet();  
    23.             //TestExpiration();  
    24.             TestPerformance();  
    25.   
    26.             Console.Read();  
    27.         }  
    28.   
    29.         private static void TestExpiration()  
    30.         {  
    31.             var engine = new CacheEngine(@"....data");  
    32.             var o = engine.Get<string, Foo>("User""wchen");  
    33.             Console.WriteLine(o != null ? o.Name : "wchen does not exist or expired");  
    34.         }  
    35.   
    36.         private static void TestPerformance()  
    37.         {  
    38.             var engine = new CacheEngine(@"....data");  
    39.             var w = new Stopwatch();  
    40.             w.Start();  
    41.             for (int i = 0; i < 100; i++)  
    42.             {  
    43.                 var o2 = engine.Get<stringstring>("PlainText""Bla");  
    44.             }  
    45.             w.Stop();  
    46.             Console.WriteLine(w.Elapsed);  
    47.         }  
    48.   
    49.         private static void TestAddGet()  
    50.         {  
    51.             var engine = new CacheEngine(@"....data");  
    52.             var f = new Foo { Name = "Wilson Chen", Age = 30, Birthday = DateTime.Now, Some = 123.456 };  
    53.             engine.Add("User""wchen", f, DateTime.Now.AddSeconds(10));  
    54.   
    55.             var t = @"Bla Bla Bla......";  
    56.             engine.Add("PlainText""Bla", t);  
    57.   
    58.             var o = engine.Get<string, Foo>("User""wchen");  
    59.   
    60.             var o4 = engine.Get<string, Foo>("User""foo");  
    61.             Console.WriteLine(o4 != null ? o4.Name : "foo does not exist");  
    62.   
    63.             var o2 = engine.Get<stringstring>("PlainText""Bla");  
    64.             Console.WriteLine(o.Name);  
    65.   
    66.             var o3 = engine.Get<stringstring>("PlainText""A");  
    67.             Console.WriteLine(o3 ?? "A does not exist");  
    68.         }  
    69.     }  
    70. }  

    说明

    项目中引用了System.Management是因为STSdb支持内存数据库,需要判断最大物理内存。如果不喜欢,大家可以移除引用,并且去掉STSdb4.Database.STSdb.FromMemory方法便可。

    下载

    点击这里下载

  • 相关阅读:
    中关村的那些黑暗的事——北漂18年(17)
    TRS OM error
    The user specified as a definer ('root'@'%') does not exist
    Spring 配置标签——util标签
    关于spring中<util:/>的配置
    Spring配置文件中指定init-method属性的作用
    spring
    could not insert: [com.trs.om.bean.UserLog] The user specified as a definer ('root'@'127.0.0.1') does not exist
    org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.trs.om.bean.User.retryCount
    U盘安装win7 raid设置
  • 原文地址:https://www.cnblogs.com/foreverme/p/3341022.html
Copyright © 2011-2022 走看看