最佳缓存解决方案

6
在基于Web的应用程序中,最好在哪个位置实现缓存?
  • 在呈现层(希望不是)?
  • 在业务逻辑层?
  • 在数据层?
我将在底层使用类似memcached或MS Velocity的东西。
我发现自己在业务逻辑层的这里写了很多更新缓存的代码,所以是否更好地在数据库服务器的数据访问层之间创建一个织物来缓存数据?
我认为这些复杂性是由于我们大多数缓存的数据都是用户特定的,并且我们在缓存中重复使用数据。 我们正在努力找到最佳解决方案。
9个回答

19

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

当完成第一步后,可以开始对应用程序进行分析,列出似乎使用了大量资源(可能是CPU、内存、I/O、数据库访问)或需要很长时间才能完成的功能列表(通常是由于相同的症状)。

一旦您有了认为可以使用缓存系统进行优化的功能列表,就需要问自己两个问题:

  • “如何同时改善所有这些功能”(宏观视角):对于这个问题,一个明显的答案通常是数据访问缓存。如果您总是获得相同的返回数据,那么通常不希望反复向数据库服务器发送相同的查询。因此,在缓存中存储这种类型的数据,并赋予聪明的生命周期,永远都是一个好主意。

  • “如何改善每个功能”(微观视角):这很棘手,您需要非常了解自己的应用程序才能找到答案。有些数据可以缓存,有些不应该缓存,有些必须不能缓存。调试器和分析器通常是此步骤的绝佳工具,因为它们可以帮助您确定为什么功能很慢,并为您提供如何进行优化的提示。

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

  • 这个功能真的需要优化吗?(对于客户而言是否有明显的收益?对于硬件?对于整个应用程序?对于其他应用程序?)
  • 我可以获得多少性能提升?(1%、200%...)
  • 优化需要花费多少时间?(1小时、12天...)
  • 优化会有多大风险?(可能会破坏应用程序或客户的东西吗?)
  • 一旦你得到了这些问题的答案,就可以与项目经理、同事甚至不与你共事的人谈论这个问题。拥有中立的意见以及非技术性(或少技术性)的意见是好的。与这些人交谈应该可以帮助你弄清楚哪些应该做和哪些不应该做。

    此时,你应该已经有一个相当明确的优化清单,你已经反复思考过了,并且在编码和测试它们方面也没有任何问题。


    我同意缓存需要深入了解您的应用程序。但是我认为我们不应该像你提到的那样,在完成第一步应用程序后就开始编写缓存解决方案。相反,我们应该更早地进行规划。因为从一开始明显需要缓存的主要部分是显而易见的,但稍后您可能会发现更多需要关注的部分。例如,在缓存世界中,字典和查找是优先考虑的,所以您应该从一开始就计划。如果您将其推迟到最后,您将需要修改每个涉及此部分的地方。 - Wahid Shalaly

    5

    缓存是一种性能优化方式,应该在瓶颈处使用。通过三次测量来确定瓶颈位置,然后再确认一次。

    当你缓存数据时,要注意数据的松散一致性,例如,您不希望缓存您的所有股票交易应用程序。


    5
    你应该考虑在每一层都进行缓存。
    缓存的最佳位置是靠近客户端请求的地方(这样你只需要尽可能少的工作来提供响应)。在 Web 应用程序中,在表示层、业务层和数据层都要进行缓存。
    (附注:如果你基本上正在用缓存逻辑在你的业务逻辑代码中随处添加,你应该真正考虑到 关注分离 避免你的代码变成一个大泥球 :-) )

    3

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


    2
    我们将其实现在业务逻辑层与表示层之间的交互中。如果来自表示层的请求已经被缓存,我们就可以跳过整个逻辑和数据访问过程。
    我强烈推荐使用MemCached而不是MS Velocity,Velocity的设置过程很麻烦!

    1

    缓存:在数据访问层实现,由业务逻辑层访问

    这意味着您必须仔细注意缓存过期的情况。


    1
    数据层。但是这很令人困惑,因为我们使用ASP.NET缓存。它具有过期和依赖性功能,非常方便。因此,我们的业务层不知道数据层可能正在缓存,但数据层使用了表示层技术进行缓存! :(

    ASP.NET的缓存问题在于它不能在应用程序和应用程序域之间进行分布或共享,而MemCached和Velocity可以实现这一点,这也是我们转向它们的原因。 - Lloyd
    非常正确。我使用SqlCacheDependency玩游戏的成功有限。我非常想使用MC或V。 - n8wrl

    1
    如果您正在缓存业务对象,并且根据您描述的3层体系结构,业务层是明显的选择。
    一个简单的设置可能是(针对单个业务对象):
    1. MyCache 是一个静态类。 2. 一个静态方法:MyCache.Retrieve(id),返回一个对象。 3. 该类使用静态 Dictionary 进行存储,并使用静态 ReaderWriterLock
    然后,Retrieve 方法执行以下操作:
    1. 你的缓存中是否有id(一个id/对象的字典)?
    2. 没有
      • 从数据库中获取对象
      • 获取ReaderWriterLock(为什么使用ReaderWriter?因为你不经常写入但经常读取)
      • 将对象添加到缓存中
    3. 是的
      • 从字典中检索对象

    这是我首选的解决方案,如果需要,您可以添加超时、清除等功能。或者使用memcached或Microsoft Enterprise Library Caching Block,但它们通常过于复杂。


    1

    我不能代表ASP.NET具体的事情说话,但我通常发现你可以在每个级别上进行缓存。您的数据层将缓存数据响应,您的表示层可能会发现需要缓存生成的表示元素(例如用户特定的样式表),等等。在大多数情况下,数据层是最重的缓存用户,如果需要,其他层将包括对象缓存。

    最困难的部分是正确地使缓存失效。在部署期间,陈旧的缓存是一个主要的头痛。确保弄清楚如何管理每个缓存对象的生命周期。基于需求的LRU缓存可用于缓存静态元素。然而,大多数数据缓存将需要明确的生命周期,无论是基于过期计时器还是与某种用户会话相关联。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接