C#架构建议:在结构中缓存数据的方法?

时间:2010-10-28 08:38:46

标签: c# caching memcached wcf

我想就C#中可行的架构问你的专家建议。

我有一个C#服务,它响应LAN上本地用户的请求,从互联网上获取数据包,并收集数据以生成结构中的数据数组。每个数据请求大约需要2秒,并返回4000个字节。每天可能会有成千上万的请求。

为了加速一切并减少带宽,我需要缓存数据处理的结果,以便第二次和后续访问立即提供给LAN上的任何其他用户(可能有> 50个用户)。

约束:

  1. 基础数据永远不会改变,即我不必担心“脏”数据(太棒了!)。
  2. 我想要缓存的数据是一个相当复杂的结构,包含DateTime,double等嵌套数组。使用大量数学方法从互联网提供的数据中收集数据。
  3. 无论缓存多少数据(即缓存必须限制大小),我都不能使用超过100MB的内存。
  4. 我无法通过数字索引索引缓存中的数据,我必须使用日期(“YYYY-MM-DD”)和唯一ID字符串(“XXXXXXXX”)的组合对其进行索引。
  5. 它必须很快,即必须从RAM中提供大部分响应。
  6. 缓存中的数据必须每24小时保存到磁盘。
  7. 目前我有以下选择:

    1. 使用私有变量(即私有列表或字典)缓存服务器类中的数据,然后偶尔将其序列化为磁盘;
    2. 使用数据库;
    3. 我对你的专家意见感兴趣。

4 个答案:

答案 0 :(得分:2)

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

关于您的要求:

  1. 缓存的生命周期最容易管理,因为后台线程会在10分钟或一小时左右的时间内扫描缓存。使用ComplexDataStructure,您可以在创建缓存时存储DateTime,并在其生命周期到期后从字典中删除密钥;

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

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

  4. 只需使用字符串;

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

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

  7. 确保正确处理锁定策略。这里最大的问题是,当不同的线程已经处理数据时,您不希望进行运算。解决方案可能是以下策略:

    1. 锁定字典;

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

    3. 当缓存项不存在时:

      1. 创建一个空缓存项;

      2. 将其添加到字典中;

      3. 锁定缓存项目;

      4. 释放字典上的锁;

      5. 进行数据处理;

      6. 将嘎吱嘎吱的数据添加到缓存项目中;

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

    4. 当缓存项已存在时;

      1. 当缓存项目确实包含有问题的数据时,请返回;

      2. 当缓存项目没有嘎吱嘎吱的数据时,请锁定缓存项目;

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

    5. 还有其他问题需要解决,但我认为这里有基础知识。

答案 1 :(得分:1)

也许像Index4Objects?

http://www.codeplex.com/i4ohttp://staxmanade.blogspot.com/2008/12/i4o-indexspecification-for.html

另外,也许可以阅读对另一个SO问题i4o vs. PLINQ的回复。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我想我找到了完美的解决方案:PostSharp + Kellerman .NET日志库。 PostSharp需要一个轻微的学习曲线(大约15分钟),但是一旦启动并运行,您可以使用[Cachable]属性注释您的方法,系统将自动为您缓存此方法的结果。它就像你可能获得的解决方案一样干净。