2010-10-28 78 views
2

我想问你的专家建议在C#中可行的架构。C#架构建议:缓存结构中的数据的方法?

我有一个C#服务,它响应来自局域网上的本地用户的请求,从互联网获取数据包,并将这些数据加工成结构中的数据阵列。每个数据请求大约需要2秒钟,并返回4000个字节。每天可能有数以万计的请求。我需要缓存数据处理的结果,以便第二次和随后的访问可以立即提供给LAN上的任何其他用户(可能有50个以上的用户)。

约束:

  1. 底层的数据不会改变,即我不担心“脏”数据(太棒了!)。
  2. 我想要缓存的数据是一个相当复杂的结构,包含嵌套的DateTime,double等数组。数据是从互联网提供的数据中使用大量数学计算的。
  3. 无论有多少数据被缓存(即缓存必须是大小限制的),我都不能使用超过100MB的内存。
  4. 我无法通过数字索引为缓存中的数据建立索引,我不得不使用date(“YYYY-MM-DD”)和唯一ID字符串(“XXXXXXXX”)的组合对其进行索引。
  5. 它必须快速,即它必须服务于RAM的大部分响应。
  6. 缓存中的数据必须每隔24小时保存到磁盘。

这里是我此刻的选择:

  1. 缓存在服务器类的数据,使用私有变量(即私人列表或字典),然后将其序列化到磁盘偶尔;
  2. 使用数据库;

我对你的专家意见很感兴趣。

回答

2

到目前为止,最简单的解决方案是使用Dictionary<string, ComplexDataStructure>

关于您的要求:

  1. 缓存的寿命是最容易被具有后台线程,做缓存曾经10分钟或小时左右的扫描来管理。在ComplexDataStructure中,创建缓存时存储DateTime,并且在其生命周期过期后从字典中删除密钥;

  2. 因为您正在存储实际的数据结构,所以复杂性不是问题;

  3. 限制尺寸可能很困难。 sizeof() equivalent for reference types?可帮助您计算对象结构的大小。这个操作不是微不足道的,但你可以用ComplexDataStructure来存储结果。然后,与用于1的线程相同的线程可以在空间不足时删除条目。更简单的解决方案可能是使用GC.GetTotalMemory()并确定您的进程的总内存使用量是否超出特定限制。然后,只需删除一个缓存项目,并在第二次运行时,当您看到您仍然使用太多内存时,请删除第二个;

  4. 只要使用一个字符串;

  5. 使用Dictionary<,>可能是因为禁食的方式;

  6. 再次使用1中的线程并实现这样的逻辑。

确保您正确处理您的锁定策略。这里最大的问题将是,当另一个线程正在处理数据时,您不希望收敛。对此的解决方案可以是以下策略:

  1. 锁定字典;

  2. 验证缓存项是否存在;

  3. 当缓存项不存在:

    1. 创建一个空的缓存项;

    2. 将其添加到词典;

    3. 锁定缓存项目;

    4. 释放字典上的锁;

    5. 做数据处理;

    6. 将crunched数据添加到缓存项目;

    7. 释放缓存项目上的锁定;

  4. 当缓存项目已经存在时;

    1. 当缓存项目实际上确实有收敛的数据时,返回该值;

    2. 当缓存项没有收集到的数据时,对缓存项进行锁定;

    3. 在锁内部,出现了嘎吱嘎吱的数据(因为锁迫使你在另一个线程上等待)。

有迹象表明,将要解决的其他问题,但我认为基本都在这里描述。

+0

很好的答案,谢谢。我不是自己实现这个功能,而是最终使用Kellerman提供的现成解决方案.NET缓存库。 – Contango 2010-10-31 20:47:07

+0

不客气。 – 2010-10-31 21:22:09

0

怎么样:使用IIS提供的内部方法?

+0

对不起,我的问题还不够清楚:我必须缓存本地数据,它包含在用C#编写的服务类中的结构中。我已经使问题变得更清楚。 – Contango 2010-10-28 09:36:25

0

我想我已经找到了完美的解决方案:PostSharp + Kellerman .NET日志库。 PostSharp需要一个轻微的学习曲线(大约15分钟),但是一旦你开始运行,你可以用属性[Cachable]注释你的方法,系统会自动为你缓存这个方法的结果。它尽可能清洁您的解决方案。