大型asp.net缓存存储的持久性方法的效率

时间:2009-01-06 03:03:15

标签: c# asp.net caching

如果有人对哪种方法更适合asp.net缓存有任何意见,那就很好奇。选项一,缓存中较少的项目较复杂,或许多项目较不复杂。

为了便于讨论,我们假设我的网站有SalesPerson和Customer对象。这些都是非常简单的类,但我不想对数据库很讨厌,所以我想懒得将它们加载到缓存中,并在我进行更改时使它们从缓存中失效 - 这很简单。

选项1 创建字典并缓存整个字典。当我需要从缓存中加载SalesPerson的一个实例时,我得到了Dictionary并对Dictionary进行了正常的键查找。

选项2 在每个项目的键前加上它并将其直接存储在asp.net缓存中。例如,缓存中的每个SalesPerson实例都将使用前缀加上该对象的键的组合,因此它可能看起来像sp_ [guid]并存储在asp.net缓存中,而且还存储在缓存中的Customer对象中。关键像cust_ [guid]。

我对选项二的恐惧之一是条目数量会变得非常大,在SalesPerson,Customer和十几个其他类别之间我可能在缓存中有25K项目,而高度重复查找类似于字符串资源的东西我在几个地方使用可能会支付罚款,而代码通过缓存的密钥集合查找它在其他25K之间。

我确信在某些时候,在缓存中存储太多项目的回报会有所减少,但我对这些问题的意见感到好奇。

4 个答案:

答案 0 :(得分:9)

最好在缓存中创建许多较小的项目,而不是创建更少,更大的项目。这是推理:

1)如果您的数据很小,那么缓存中的项目数量将相对较少,并且不会产生任何差异。从缓存中获取单个实体比获取字典然后从该字典中提取项目更容易。

2)一旦数据变大,缓存可用于以智能方式管理数据。 HttpRuntime.Cache对象使用最近最少使用(LRU)算法来确定缓存中的哪些项目将过期。如果缓存中只有少量高度使用的项目,则此算法将无用。但是,如果缓存中有许多较小的项目,但其中90%在任何给定时刻都没有使用(非常常见的使用启发式),那么LRU算法可以确保那些看到活动使用的项目保留在缓存中同时逐出较少使用的物品,以确保使用过的物品有足够的空间。

随着应用程序的增长,能够管理缓存中的内容的重要性将是最重要的。此外,我还没有看到在缓存中拥有数百万个密钥会导致性能下降 - 哈希表速度极快,如果您发现问题,可以通过更改缓存密钥的命名约定来轻松解决,以优化它们用作哈希表键。

答案 1 :(得分:1)

ASP.NET缓存使用自己的字典,因此使用其字典来查找字典以进行查找以检索对象似乎不是最佳的。字典使用哈希表,这是您可以执行的最有效的查找。我想,使用你自己的词典只会增加更多的开销。我不知道哈希表的收益递减,但我认为这将是存储大小,而不是查找时间。

我会关心让你工作更轻松的事情。如果让Cache更有条理将使您的应用程序更容易理解,调试,扩展和维护,那么我会这样做。如果它使那些事情变得更复杂,那么我就不会这样做。

正如nullvoid所提到的,这都是假设你已经探讨了缓存的更大含义,其中包括衡量性能增益与性能影响。你在谈论存储大量的对象,这意味着大量的缓存流量。我只会在缓存中存储一​​些你可以衡量从而获得性能提升的东西。

答案 2 :(得分:1)

我们构建了一个使用缓存来存储所有资源的应用程序。该应用程序是多语言的,因此对于应用程序中的每个标签,我们至少有三个翻译。我们在第一次需要时加载(Label,Culture)组合,然后只有在数据库中由ad​​min和admin更改时才从缓存中过期。即使缓存中包含100000个项目,此方案也能很好地工作。我们只关注配置缓存和到期策略,以便我们真正受益于缓存。我们使用no-expiration,因此项目将被缓存,直到重置工作进程或项目有意过期为止。我们还注意为键的值定义域,以便以最少的字符数唯一地标识特定文化中的标签。

答案 3 :(得分:0)

我将假设您已经考虑了数据从多个用户变化的所有影响,以及在处理冲突数据方面这将如何影响缓存数据。缓存实际上只是针对相关的静态数据。

从效率的角度来看,我认为如果你正确使用.net序列化,你将会受益于以较大类型的序列化集合而不是单独的基本类型的形式将数据存储在缓存中。

从维护角度来看,这也是一种更好的方法,因为您可以创建一个强类型对象来表示数据,并使用序列化将其强制转换为缓存和销售人员/客户对象。