【问题标题】:Use IMemoryCache singleton-per-repository?使用 IMemoryCache 单个存储库?
【发布时间】:2019-07-03 16:26:04
【问题描述】:

我正在将 IMemoryCache 集成到一个项目中,并且我将竭尽全力确保每个存储库或提供程序中的密钥不会发生冲突(即提出一个密钥空间)。但后来我突然想到,为什么不为每个存储库/提供者提供他们自己的 IMemoryCache 单例实例——即一个命名的单例。这将保证密钥永远不会发生冲突,并且一个存储库永远无法访问另一个存储库的内部状态。我的原始方面还说这可能会提高性能,因为现在每个存储库都不会竞争 IMemoryCache 的内部锁。

但我不会假装理解 IMemoryCache 如何管理它的所有逻辑。也许拥有一个应用程序范围的单例实例很重要,这样它才能以更高性能的方式管理缓存条目的生命周期。

基本上,我从未见过有人将单例存储库模式与 IMemoryCache 一起使用,因此我正在征求对这种方法的反馈。

谢谢

【问题讨论】:

    标签: c# caching .net-core


    【解决方案1】:

    我相信最初的 .NET Full Framework MemoryCache 旨在通过MemoryCache.Default 属性用作单例实例。这是因为它在名为MemoryPressure 的东西上运行。关于这个神奇的MemoryPressure 是如何计算的,几乎没有任何文档。毫无疑问,它在多个实例上可能不太聪明。

    现在的偏好似乎是对缓存设置大小限制。 MemoryCache.Default 静态属性不再存在于 dotnet 核心版本中,并且似乎不存在表明多实例是反模式的警告。此外,MemoryCacheOptions.CompactOnMemoryPressure 现在似乎已被弃用,并且首选是提供固定大小。我看不出使用多个实例有什么问题。

    【讨论】:

      【解决方案2】:

      这是我创建的一个 linqpad 示例。我想这就是你要找的东西:

      void Main()
      {
          DataTable dt = new DataTable();
      
          DateTime start = DateTime.Now;
      
          Random _rand = new Random();
          List<int> result = Enumerable.Range(1, 6000)
          .Select(x => x++)
          .ToList();
          result.AsParallel<int>().ForAll(c =>
          {
              Util.GetFromCache("datatable", c);
              System.Threading.Thread.Sleep(1);
          });
      
          DateTime.Now.Subtract(start).Seconds.Dump();
          "....DONE.....".Dump();
      
      }
      
      public static class Util
      {
          private static readonly object _Lock = new object();
      
          public static object GetFromCache(string cachename, int i)
          {
              object obj = MemoryCacher.GetValue(cachename);
      //      if (i == 5) //when time is up - reset token, update DB and add to cache es example i set a count=5
      //      {
      //          obj = null;
      //          MemoryCacher.Delete(cachename);
      //      }
              if (obj == null)
              {
                  lock (_Lock)
                  {
                      obj = MemoryCacher.GetValue(cachename);
                      if (obj == null)
                      {
                          $"{i} from DATA".Dump();
                          obj = GetData();
                          MemoryCacher.Delete(cachename);
                          MemoryCacher.Add(cachename, obj, DateTimeOffset.Now.AddSeconds(5));
                          return obj;
                      }
                      $"{i} from CACHE with lock".Dump();
                  }
              }
              $"{i} from CACHE".Dump();
              return obj;
          }
      
          public static DataTable GetData()
          {
              DataTable dt = new DataTable();
      
              FileInfo fi = new FileInfo("c:\\1\\text.txt");
              dt = CSVtoDS(fi.FullName, true).AsEnumerable().Take(10).CopyToDataTable();
              return dt.Dump("call");
          }
      
          public static DataTable CSVtoDS(string filePath, bool isFirstLineHeader)
          {
              DataTable dt = new DataTable();
              using (TextReader tr = File.OpenText(filePath))
              {
                  string strRow = string.Empty;
                  string[] arrColumns = null;
                  int indx = 0;
                  while ((strRow = tr.ReadLine()) != null)
                  {
                      //set up columns
                      if (indx == 0)
                      {
                          arrColumns = strRow.Split('\t')[0].Split(',').Select(x => x.Replace(" ", "_")).ToArray();
                          if (dt.Columns.Count != arrColumns.Length + 1)
                              for (int i = 0; i <= arrColumns.Length - 1; i++)
                              {
                                  if (isFirstLineHeader)
                                      dt.Columns.Add(new DataColumn(arrColumns[i]));
                                  else
                                      dt.Columns.Add(new DataColumn());
                              }
                          indx = 1;
                      }
                      else
                      {
                          DataRow dr = dt.NewRow();
                          dr.ItemArray = strRow.Split(',');
                          dt.Rows.Add(dr);
                      }
                  }
                  tr.Close();
              }
              return dt;
          }
      
          public static class MemoryCacher
          {
              public static object GetValue(string key)
              {
                  MemoryCache memoryCache = MemoryCache.Default;
                  return memoryCache.Get(key);
              }
      
              public static void Add(string key, object value, DateTimeOffset absExpiration)
              {
                  MemoryCache memoryCache = MemoryCache.Default;
                  memoryCache.Set(key, value, absExpiration);
              }
      
              public static void Delete(string key)
              {
                  MemoryCache memoryCache = MemoryCache.Default;
                  if (memoryCache.Contains(key))
                  {
                      memoryCache.Remove(key);
                  }
              }
          }
      }
      

      【讨论】:

      • OP 又要求什么?
      猜你喜欢
      • 2019-10-06
      • 2019-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-09
      • 1970-01-01
      相关资源
      最近更新 更多