PHP APC缓存:缓存还是不缓存?

8

我对缓存没有任何经验,所以这可能是一个愚蠢的问题,但是什么时候应该缓存数据呢?我甚至找不到一个谈论这个话题的网站,但这可能只是我的搜索技巧不够好,或者需要考虑的变量太多了吗?

我最可能会使用APC。有没有人有一些关于最少需要缓存数据量的示例?例如,假设您有一个包含100项的数组,并对其使用foreach循环进行一些简单的数组操作,您应该缓存结果吗?如果它有1000项、10000项等,情况如何?

您应该缓存数据库查询结果吗?哪种类型的查询应该进行缓存?我认为一个简单的select和几个连接mysql db的语句不需要缓存,或者需要吗?假设mysql查询缓存已经打开,那么这是否意味着您不需要在应用程序层缓存,或者仍然需要缓存?

如果您实例化一个对象,您应该缓存它吗?如何确定是否应该缓存它?所以,一个关于什么可以缓存的通用指南会很好,例如也会非常有帮助,谢谢。

2个回答

10
当您正在使用APC/memcache/WinCache/redis等缓存已从数据库中读取的数据时,应该意识到除非您明确编写代码来保持数据库与缓存同步,否则当数据库更新时,缓存不会被更新。因此,缓存在数据库中的数据不经常更改时最有效,但是检索该数据需要更复杂和/或更昂贵的查询(否则,当您需要时可以直接从数据库读取它)... 因此返回相同数据记录的昂贵连接查询是主要候选对象。
并且始终测试查询是否从数据库中读取比从缓存中读取更快。正确的数据库索引可以大大提高数据库访问时间,特别是由于大多数数据库还维护其自己的内部缓存,因此除非数据库开销有所证明,否则不要使用APC或类似的方法来缓存数据。
您还需要注意缓存中的空间使用情况。大多数缓存都是固定大小的,您不想过度填充它们...因此不要使用它们来存储大量数据。使用APC提供的apc.php脚本监视缓存使用情况(确保它不对任何访问您站点的人公开),但安全性差。
在将对象存储在缓存中时,对象在存储时将被序列化(),在检索时将被反序列化(),因此存在开销。具有资源属性的对象将失去该资源,因此不要存储数据库访问对象。
明智地仅使用缓存来存储所有/多个用户都可以访问的信息,而不是特定于用户的数据。对于用户会话信息,请使用普通的PHP会话。

4
@Joker,额外补充一点,如果你还不知道,APC提供了两种类型的缓存:一个是由PHP内部使用的操作码缓存,用于“加快速度”,另一个是用户缓存,可用于存储数据。在这里,您将需要使用用户缓存。希望对那些遇到类似问题的人有所帮助。(如果这已经是家常便饭了,请见谅,但希望对其他人有所裨益。) - James Butler
是的,我知道有操作码缓存,如果启用了apc,它就会自动工作。当你说应该测试一下查询是从数据库还是缓存中读取更快时,我该如何进行测试?什么时候应该缓存普通数据?例如我的foreach循环示例。 - Joker
@Joker - 测试的方法是实际尝试(使用两种方法)并测量时间...没有绝对的数学可以事先告诉你,尽管在数据库查询上使用EXPLAIN可能会给出一些提示。请记住,您始终应确保数据库上有最佳索引。您的循环示例也没有任何“硬性规定”...它是一种需要根据情况评估的东西。我只能说“不要仅仅因为缓存而缓存”,只有在真正可衡量的好处时才这样做。 - Mark Baker
我其实在想如何准确地测量时间。例如,您是否只需在前后运行microtime并找到差异? - Joker
1
@Joker - 这是一种方法,我自己也使用过...但我更喜欢使用Apache基准测试,它允许我模拟并发访问,并提供了更全面的时间统计信息。(http://httpd.apache.org/docs/2.0/programs/ab.html) - Mark Baker

0
简单的答案是在事情变慢时缓存数据。显然,对于任何中大型应用程序,您需要做更多的规划,而不仅仅是等待并采取行动。但是对于绝大多数网站来说,要问自己的问题是“您对加载时间满意吗?”当然,如果您像我一样对加载时间着迷,您将想尝试使其更快,无论如何。
接下来,您必须确定导致缓慢的具体原因。您可能认为您的应用程序代码是源头,但值得检查是否存在其他外部因素,例如大型页面文件大小、过多请求、无gzip等。使用类似http://tools.pingdom.com/的网站或像yslow这样的扩展作为开始。(快速提示:确保keepalives和gzip正在运行)。
假设问题是应用程序代码的执行持续时间,您将需要使用诸如xdebug(http://www.xdebug.org/)之类的工具对代码进行分析,并使用kcachegrind或wincachegrind查看输出结果。那将让您知道代码的哪些部分需要长时间运行。从那里,您将根据需要缓存和缓存方式(或改进代码逻辑)做出决策。

问题的可能性和相关解决方案有很多,我猜测也没有意义。因此,一旦您确定了问题,您可能希望发布一个新的问题,与解决该特定问题有关。我会说,如果不正确使用,mysql查询缓存可能会产生反作用。此外,我通常避免使用APC用户缓存,而是选择memcached。


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