最佳缓存解决方案

时间:2009-06-23 13:35:24

标签: asp.net-mvc caching memcached

在基于网络的应用中实施缓存的最佳位置在哪里?

  • 在表示层(希望不是)?
  • 在业务逻辑层?
  • 在数据层?

我将使用像memcached或MS Velocity这样的东西。

我只是发现自己编写了如此多的代码来更新业务逻辑层中的缓存,那么在数据库服务器的数据访问层之间创建一个结构来缓存数据会更好吗? / p>

我认为这些复杂情况归结为这一事实,我们缓存的大多数数据都是用户特定的,我们正在复制缓存中的数据。我们努力寻找最佳解决方案。

9 个答案:

答案 0 :(得分:19)

缓存是一个重要的部分或Web应用程序,但没有适合每个项目的神奇解决方案。在应用程序运行之前进行优化通常是个坏主意。在问自己应该在哪里实现缓存层之前,第一步是确保您的应用程序运行良好(即使速度很慢),而不进行任何缓存优化。

当实现第一步时,您可以开始分析应用程序,列出似乎使用大量资源的功能(可能是CPU,内存,I / O,数据库访问)或花费大量时间完成(通常是因为相同的症状)。

如果您有一个您认为可以使用缓存系统优化的功能列表,那么您需要问自己两个问题:

  • “我如何同时改进所有这些功能”(宏观焦点):这个问题的一个明显答案通常是数据访问缓存。如果您获得的数据始终相同,您通常不希望一遍又一遍地向数据库服务器发送相同的查询。因此,将这种类型的数据存储在缓存中,具有巧妙的使用寿命,总是一个好主意。

  • “我如何改进每个功能”(微焦点):这很棘手,你需要很好地理解你的应用程序来解决这个问题。有些数据可以缓存,有些则不应该,有些则不能。调试器和分析器通常是此步骤的绝佳工具,因为它们可帮助您确定功能缓慢的原因,并为您提供有关如何优化功能的提示。

您要弄清楚的优化可能与您的应用程序的任何层(表示,业务逻辑,数据)有关,但这并不意味着您应该全部实现它们。您应该考虑以下几个重要事项:

  • 这个功能真的需要优化吗? (对于客户来说,这是一个明显的收益吗?对于硬件?对于整个应用程序?对于其他应用程序?)
  • 我可以获得什么样的性能提升? (1%,200%,...)
  • 优化它需要多长时间? (1小时,12天,......)
  • 优化它有多大风险? (它可能会破坏应用程序的内容吗?对于客户来说?)

一旦您获得了这些问题的答案,就该与您的项目经理,您的同事,甚至那些不与您一起处理该应用程序的人员讨论这个问题。持中立意见是好的,并且有非技术性(或技术性较低)的意见。与这些人交谈应该可以帮助你弄清楚应该做什么和不该做什么。

此时你应该有一个非常清楚的优化列表,你想过好几次,你应该没有问题编码和测试它们。

答案 1 :(得分:5)

缓存是一种性能优化,因此在瓶颈所在的位置进行缓存。你可以通过测量它三次然后再测量它来知道瓶颈在哪里。

请注意缓存时数据的宽松一致性,例如你不想缓存你所有的股票交易应用程序。

答案 2 :(得分:5)

您应该考虑在每个层进行缓存。

缓存的最佳位置是尽可能接近客户端请求(因此您尽可能少地为响应提供服务)。在Web应用程序中,是在表示层,业务层和数据层。

(旁注:如果你基本上用缓存逻辑来处理你的业务逻辑代码,你应该真正研究seperation of concerns以避免你的代码成为泥浆的大球:-))

答案 3 :(得分:3)

数据层 - 此层上方的所有层不需要知道数据的来源。我也只会缓存不太易变的数据,或者包含一些过期策略。

答案 4 :(得分:2)

我们在与表示层的交互之间的业务逻辑层实现它。如果来自表示层的请求进入并缓存,我们就可以跳过大量的逻辑和数据访问。

我强烈推荐MemCached而不是MS Velocity,Velocity很难设置!

答案 5 :(得分:1)

缓存:已实施,位于数据访问层,业务逻辑层已访问

这意味着你必须仔细注意缓存过时。

答案 6 :(得分:1)

数据层。但它很混乱,因为我们使用ASP.NET缓存。凭借其过期和依赖功能,它非常方便。所以我们的业务层不知道数据层可能是缓存,但数据层使用表示层技术进行缓存! :(

答案 7 :(得分:1)

如果你正在缓存业务对象,并且给出了你所描述的3层,那么业务层就是显而易见的。

一个简单的设置(对于单个业务对象):

  1. MyCache是​​一个静态类
  2. 一个静态方法:MyCache.Retrieve(id),返回一个对象
  3. 该类使用静态Dictionary进行存储,使用静态ReaderWriterLock
  4. 然后,Retrieve方法执行以下操作:

    1. 缓存中的ID(id / object的Dictionary)?
      • 从数据库中抓取对象
      • 来自AquireWriterLock
      • ReaderWriterLock(为什么ReaderWriter?因为你不是经常写作而是经常阅读)
      • 将对象添加到缓存
      • 从字典中检索对象
    2. 这是我的首选解决方案,如果需要,您可以添加超时,清除等。或者使用memcached或Microsoft Enterprise Library Caching Block,但它们通常是矫枉过正的。

答案 8 :(得分:1)

我不能代表ASP.NET特定的东西,但我一般都发现你可以在每个级别缓存。您的数据层将缓存数据响应,您的表示层可能会发现需要缓存生成的表示元素(例如,用户特定的样式表)等。在大多数情况下,数据层是最重的缓存用户,其他层将包括如果证明有必要使用对象缓存。

最难的部分是让缓存失效正常工作。过时的缓存是部署过程中的主要问题。确保弄清楚如何管理每个缓存对象的生命周期。 LRU缓存可以很好地根据需求缓存静态元素。但是,大多数数据缓存都需要一个明确的生命周期,无论它是基于到期计时器还是与某种用户会话相关联。