<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      基于STSdb和fastJson的磁盤/內存緩存

      2013-07-03 10:50  靈感之源  閱讀(4008)  評論(7)    收藏  舉報

      更新

      1. 增加了對批量處理的支持,寫操作速度提升5倍,讀操作提升100倍

      2. 增加了對并發的支持

      需求

      業務系統用的是數據庫,數據量大,部分只讀或相對穩定業務查詢復雜,每次頁面加載都要花耗不少時間(不討論異步),覺得可以做一下高速緩存,譬如用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 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));
                  }
              }
      
              private string GetExpirationTable(string Category)
              {
                  return KeyExpiration + "_" + Category;
              }
      
              public void Add<K, V>(string Category, IEnumerable<KeyValuePair<K, V>> Items, DateTime? ExpirationDate)
              {
                  lock (syncRoot)
                  {
                      var engine = Engine;
                      var table = engine.OpenXIndex<K, string>(Category);
                      Items.ForEach(i =>
                          {
                              var key = i.Key;
                              var data = i.Value;
                              //will only serialize object other than string
                              var result = typeof(V) == typeof(string) ? data as string : JSON.Instance.ToJSON(data);
                              table[key] = result;
                              table.Flush();
      
                              //specify expiration
                              var expiration = engine.OpenXIndex<K, DateTime>(GetExpirationTable(Category));
                              //default 30 mins to expire from now
                              var expirationDate = ExpirationDate == null || ExpirationDate <= DateTime.Now ? DateTime.Now.AddMinutes(30) : (DateTime)ExpirationDate;
                              expiration[key] = expirationDate;
                              expiration.Flush();
                          });
                      engine.Commit();
      
                      //only dispose disk-based engine
                      if (!isMemory)
                          engine.Dispose();
                  }
              }
      
              public void Add<K>(string Category, K Key, object Data, DateTime? ExpirationDate)
              {
                  Add<K, object>(Category, new List<KeyValuePair<K, object>> { new KeyValuePair<K, object>(Key, Data) }, ExpirationDate);
              }
      
              private string GetFile(bool IsData)
              {
                  if (!Directory.Exists(dataPath))
                      Directory.CreateDirectory(dataPath);
                  return dataPath + "SuperCache." + (IsData ? "dat" : "sys");
              }
      
              public List<KeyValuePair<K, V>> Get<K, V>(string Category, IEnumerable<K> Keys)
              {
                  var result = new List<KeyValuePair<K, V>>();
                  lock (syncRoot)
                  {
                      var engine = Engine;
                      var table = engine.OpenXIndex<K, string>(Category);
                      var expiration = engine.OpenXIndex<K, DateTime>(GetExpirationTable(Category));
                      var isCommitRequired = false;
      
                      Keys.ForEach(key =>
                          {
                              string buffer;
                              V value;
                              if (table.TryGet(key, out buffer))
                              {
                                  //will only deserialize object other than string
                                  value = typeof(V) == typeof(string) ? (V)(object)buffer : JSON.Instance.ToObject<V>(buffer);
                                  DateTime expirationDate;
                                  //get expiration date
                                  if (expiration.TryGet(key, out expirationDate))
                                  {
                                      //expired
                                      if (expirationDate < DateTime.Now)
                                      {
                                          value = default(V);
                                          table.Delete(key);
                                          table.Flush();
                                          expiration.Delete(key);
                                          expiration.Flush();
                                          isCommitRequired = true;
                                      }
                                  }
                              }
                              else
                                  value = default(V);
      
                              result.Add(new KeyValuePair<K, V>(key, value));
                          });
      
                      //only need to commit write actions
                      if (isCommitRequired)
                          engine.Commit();
      
                      //only dispose disk-based engine
                      if (!isMemory)
                          engine.Dispose();
                  }
                  return result;
              }
      
              public V Get<K, V>(string Category, K Key)
              {
                  var buffer = Get<K, V>(Category, new K[] { Key });
                  var result = buffer.FirstOrDefault();
                  return result.Value;
              }
          }
      }
      

        

        

       

      新建

      構造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 System.Threading;
      using System.Threading.Tasks;
      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 DateTime? Birthday { get; set; }
          }
      
          class Program
          {
              static void Main(string[] args)
              {
                  //TestAddGet();
      
                  //Thread.Sleep(4000);
                  //TestExpiration();
      
                  TestPerformance();
      
                  //TestConcurrent();
      
                  Console.Read();
              }
      
              private static void TestConcurrent()
              {
                  var w = new Stopwatch();
                  w.Start();
                  Parallel.For(1, 3, (a) =>
                      {
                          var employees = Enumerable.Range((a - 1) * 1000, a * 1000).Select(i => new KeyValuePair<int, string>(i, "Wilson " + i + " Chen"));
                          var engine = new CacheEngine(@"..\..\data");
                          engine.Add<int, string>("Employee", employees, DateTime.Now.AddMinutes(1));
                      });
                  w.Stop();
                  Console.WriteLine("add:" + w.Elapsed);
      
                  var engine2 = new CacheEngine(@"..\..\data");
                  var o = engine2.Get<int, string>("Employee", 1005);
                  Console.WriteLine(o);
              }
      
              private static void TestPerformance()
              {
                  var engine = new CacheEngine(@"..\..\data");
                  var w = new Stopwatch();
      
                  w.Start();
                  var employees = Enumerable.Range(0, 1000).Select(i => new KeyValuePair<int, string>(i, "Wilson " + i + " Chen"));
                  engine.Add<int, string>("Employee", employees, DateTime.Now.AddMinutes(1));
                  w.Stop();
                  Console.WriteLine("add:" + w.Elapsed);
      
                  /*w.Restart();
                  employees.ForEach(key =>
                      {
                          var o1 = engine.Get<int, string>("Employee", key.Key);
                      });
                  w.Stop();
                  Console.WriteLine("individual get:" + w.Elapsed);*/
      
                  w.Restart();
                  var keys = employees.Select(i => i.Key);
                  var o = engine.Get<int, string>("Employee", keys);
                  w.Stop();
                  Debug.Assert(o.Count == keys.Count());
                  Console.WriteLine("get:" + w.Elapsed);
              }
      
              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(5));
      
                  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 o3 = engine.Get<string, string>("PlainText", "A");
                  Console.WriteLine(o3 ?? "A does not exist");
              }
          }
      }
      

        

        

        

       

      說明

      項目中引用了System.Management是因為STSdb支持內存數據庫,需要判斷最大物理內存。如果不喜歡,大家可以移除引用,并且去掉STSdb4.Database.STSdb.FromMemory方法便可。

      下載

      點擊這里下載

      主站蜘蛛池模板: 精品自拍偷拍一区二区三区| 999福利激情视频| 欧洲精品色在线观看| 国产福利酱国产一区二区| 日本亚洲一区二区精品久久| 亚洲精品二区在线播放| 国产成人无码性教育视频| 国产精品一区二区三区自拍| 美日韩精品一区二区三区| 在线看片免费不卡人成视频| 99在线精品国自产拍中文字幕| 国产精品第二页在线播放| 亚洲AVAV天堂AV在线网阿V| 国产精品一区二区无线| 国产呦交精品免费视频| 麻豆一区二区三区精品蜜桃| 黄频在线播放观看免费| 国产亚洲精品中文字幕| 99久久精品国产一区色| 留坝县| 国产精品 无码专区| 波多野结衣美乳人妻hd电影欧美 | 久久香蕉国产线看观看猫咪av| 日韩中文字幕人妻精品| 最新精品国偷自产在线| 国产午夜亚洲精品国产成人| 俄罗斯老熟妇性爽xxxx| 欧美成人午夜精品免费福利| 国产精品日日摸夜夜添夜夜添2021 | 丰满无码人妻热妇无码区| 成人无码www在线看免费| 男人和女人做爽爽免费视频| 国内极度色诱视频网站| 青草青草久热国产精品| 天堂av资源在线免费| 亚洲欧洲精品日韩av| 国产成AV人片久青草影院 | 亚洲小说乱欧美另类| 色老99久久九九爱精品| 伊人久久精品无码麻豆一区| 欧美日韩不卡视频合集|