如何实现Web应用程序的缓存

时间:2011-03-05 19:59:37

标签: java database caching web-applications

使用Java和NoSQL数据库开发的缓存Web应用程序数据的不同方法有哪些?数据库还提供缓存,它们是唯一的&总是最好的选择,用于缓存?

我还能如何在应用程序上缓存用户数据。应用程序包含非常用户特定的数据,如社交网络。是否有一些简单的拇指规则应该缓存什么类型的东西?

我还可以使用Java在应用服务器上缓存数据吗?

2 个答案:

答案 0 :(得分:25)

如果你想要一个经验法则,迈克尔·杰克逊(不是那个迈克尔·杰克逊)所说的就是:

  1. 程序优化的第一条规则:不要这样做
  2. 程序优化的第二条规则(仅供专家使用!):尚未执行
  3. 古老的传统是,在您分析之前,您不会进行优化 - 也就是说,直到您有确凿的证据证明实际需要优化的内容。缓存是一种优化;它很可能对你的应用程序很重要,但是在你能够加载你的应用程序并查看需要很长时间才能获得的对象(从数据库加载或其他任何东西)之前,你将不知道需要什么cacheing。无论你有多聪明,或者你在这里得到什么建议都没关系 - 直到你这样做,你将不知道需要缓存什么。

    至于你可以缓存的东西,它是什么,但我想你可以将它分为三组:

    1. 来自数据库的新鲜事物。这些很容易缓存,因为在您访问数据库时,您可以获得缓存密钥所需的标识信息(主键,查询参数等)。通过缓存它们,您可以节省从数据库中获取它们所需的时间 - 这涉及IO,因此它可能非常大。
    2. 通过域模型中的计算产生的东西(也许是社交应用中的新闻源)。这些可能更难以缓存,因为更多的上下文信息会产生它们;您可能必须重构代码以创建所需信息的单个点,因此您可以对其应用缓存。或者您可能已经发现它已存在。缓存这些将保存获取制作它们的信息所需的所有数据库访问,以及所有计算;计算所花费的时间可能是也可能不是IO所用时间的重要补充。使这种缓存的东西失效可能比纯数据库对象困难得多。
    3. 发送到浏览器的内容 - 页面或页面片段。这些可以非常容易缓存,因为在设计合理的应用程序中,它们可以通过URL或URL和用户的组合进行唯一标识。缓存这些将保存您应用中的所有计算;它甚至可以避免服务请求,因为它可以通过位于应用服务器前面的reverse proxy来完成。两个问题。首先,它使用了大量的内存:从几千字节的对象渲染的页面可能是几十或几百千字节(我的Facebook主页是50 kB)。这意味着你必须保存大量的计算才能使它比在数据库或域模型层缓存更好,并且在一个设计合理的应用程序中,域模型和HTML之间的计算量并不多。其次,失效比在域模型中更难,并且很可能经常发生 - 任何改变页面或片段的东西都需要使缓存无效。
    4. 最后,实际的机制:从简单和正在进行的事情开始,如有限大小的地图和最近最少使用的驱逐政策。这很简单但很有效。像EHCache这样的进程外更复杂,但有两个优点:你可以在多个进程之间共享缓存(如果你有一个集群很有帮助,你可能会在某个时候),并且你可以将数据存储在垃圾收集器的哪里不会看到它,这可能会节省一些CPU时间(可能 - 这是一个太大的主题,不能进入这里)。

      但我重申了我的第一点:在你知道需要缓存什么之前不要缓存,一旦你这样做,请注意缓存优势的限制,并尽量保持缓存策略尽可能简单(但当然没有简单)。

答案 1 :(得分:7)

我假设您正在构建一个相对典型的Web应用程序:

  1. 有一个用于持久性的服务器
  2. 多个网络服务器
  3. 通过负载均衡器
  4. 通过粘性会话将经过身份验证的用户绑定到单个服务器

    现在,随着陈述回答你的问题。大多数持久性,数据库或NoSQL,可能都内置了某种缓存,如果你重复执行相同的简单查询(例如通过主键检索),它就能够缓存结果。但是,查询越复杂,持久性就越不可能对其执行缓存。此外,如果只有一个服务器用于持久化(即没有分片或写主/读从属),它很快就会成为瓶颈。因此,您希望执行的应用程序级缓存通常应在Web服务器上进行,以减少数据库的负载。

    就应该缓存的内容而言,启发式是经常访问和/或生成成本高的项目(就数据库/ Web服务器处理/内存而言)。典型的候选者是主页和网站的任何其他登陆页面 - 通常最好的方法是生成静态文件并提供服务。接下来的部分取决于您的应用程序,但通常最有效的策略是尽可能接近最终结果进行缓存 - 通常是提供的HTML。对于您的社交网络,这可能是特色更新或其他类似的列表。

    就用户会话而言,这些绝对是缓存的理想选择。在这种情况下,您可能会因明智地使用Web服务器的会话范围(假设是JSP服务器)而获得很多好处。这些数据存储在内存中,一旦用户在每个页面上进行身份验证(例如,名字和姓氏),就可以保存用户特定信息。

    现在要考虑的最后一件事是处理缓存失效,这真的是所有这些(naming stuff is the other hard thing in computer science)的难点。在这种情况下,正如其他人所提到的那样使用memcached或ehcache之类的东西是正确的方法。 ehcache可以轻松地与您的Java应用程序一起运行,并且可以很好地使用过期的东西,使用最近最少使用和最少使用的策略,并允许您使用内存和磁盘进行缓存。您需要考虑的是您需要在此计划之前从缓存中过期的情况,因为数据已更改。在这种情况下,您需要在应用程序的体系结构中处理这些依赖项,以便它适当地读取/写入缓存。