我应该使用瞬时API来存储HTML字符串或对象吗?

时间:2016-01-23 作者:Marvin3

让我们假设有一个插件,它显示20个相关帖子(每个帖子)和一个非常复杂的查询。然后使用此查询中的数据,构建复杂的HTML布局。此外,应该注意的是,该插件是公共的,可以安装在任何配置的服务器上。

类似于:

/* complex and large query */
$related_posts = get_posts( ... );

$html_output = \'\';
foreach($related_posts as $key => $item) {
     /* complex layout rendering logic (but not as slow as the previous query) */   
     $html_output .= ...;
}
所以我的问题是:

缓存此类数据最安全、最正确的方法是什么$related_posts 数组,或$html_output 一串如果我缓存$html_ouput 字符串,是否会达到最大大小限制?在保存之前,我应该gzip吗

3 个回复
最合适的回答,由SO网友:kovshenin 整理而成

我应该在这里使用瞬态API吗?

WordPress安装瞬态存储在wp\\U选项表中,仅在核心升级期间清除。假设您有50000篇文章,那么选项表中还有50000行。显然,它们被设置为自动加载=否,因此不会消耗所有内存,但还有一个警告。

选项表中的自动加载字段没有索引,这意味着wp_load_alloptions() 将执行全表扫描。行数越多,所需时间越长。您越频繁地写入选项表,MySQL的内部缓存的效率就越低。

如果缓存的数据与帖子直接相关,最好将其存储在post meta中。这还将在每次需要显示缓存内容时为您保存一个查询,因为在WP\\U查询中进行后期检索时(通常)会对后期元缓存进行预处理。

元值的数据结构可能会有所不同,如果缓存的值过时,您可以使用时间戳并执行昂贵的查询,就像瞬态一样。

要记住的另一个重要想法是,在具有持久对象缓存的环境中,WordPress瞬态可能是不稳定的。这意味着,如果您在一段时间内将缓存数据存储24小时,则绝对不能保证它在23小时、12小时甚至5分钟内可用。许多安装的对象缓存后端都是内存中的键值存储,如Redis或Memcached,如果分配的内存不足,无法容纳较新的对象,则会逐出较旧的项目。这是元存储方法的巨大胜利。

失效也可以更智能,即为什么要在X小时内使相关帖子缓存失效?是因为某些内容发生了变化吗?是否已添加新帖子?是否已分配新标记?根据您的“复杂而庞大的查询”,只有在发生了将改变查询结果的事情时,您才可以选择使其无效。

我应该使用瞬态API缓存$related\\u posts数组还是$html\\u输出字符串?如果我缓存$html\\u输出字符串,它会达到最大大小限制吗?在保存之前,我应该gzip吗?

这在很大程度上取决于字符串的大小,因为这是将在PHP、MySQL等之间流动的数据。您需要尽最大努力达到MySQL的限制,但例如,Memcached默认的每个对象限制只有1 mb。

“复杂布局渲染逻辑”实际需要多长时间?通过探查器运行它以找出答案。它的速度很快,很可能永远不会成为瓶颈。

如果是这样,我建议缓存帖子ID。不是WP\\u Post对象,因为这些对象将包含完整的Post内容,而只是一个Post id数组。那就用WP_Query 使用post__in 这将导致通过主键进行非常快速的MySQL查询。

也就是说,如果每个项目所需的数据非常简单,可能是标题、缩略图url和永久链接,那么您可以只存储这三个数据,而不需要额外的MySQL往返开销,也不需要缓存很长的HTML字符串。

哇,这是很多词,希望能有所帮助。

SO网友:gmazzap

不是所有的WP代码都是公共代码,如果你要发布一些公共的东西,那么所有的东西kovshenin 所说的完全正确。

如果要为自己或公司编写私有代码,情况就不同了。

外部对象缓存是一个很大的好处,在任何情况下,设置外部持久对象缓存very recommended, 当你可以的时候。

kovshenin在回答中所说的关于瞬态和MySQL的所有事情都是非常真实的,考虑到WP本身和一堆插件都利用了对象缓存。。。那么,您所获得的性能改进,绝对值得(少量)建立一个像Redis或Memcached这样的现代缓存系统。

缓存的值可能不存在:这很好,而且,是的,外部对象缓存not 可信赖的你永远不应该相信有一个短暂的存在。如果缓存的位置不在应该的位置,则需要确保它正常工作。

缓存不是存储,缓存是缓存。

有选择地使用缓存参见以下示例:

function my_get_some_value($key) {
   // by default no cache when debug and if no external object_cache
   $defUse = ! (defined(\'WP_DEBUG\') && WP_DEBUG) && wp_using_ext_object_cache();
   // make the usage of cache filterable
   $useCache = apply_filters(\'my_use_cache\', $defUse);
   // return cached value if any
   if ($useCache && ($cached = get_transient($key))) {
     return $cached;
   }
   // no cached value, make sure your code works with no cache
   $value = my_get_some_value_in_some_expensive_way();
   // set cache, if allowed
   $useCache and set_transient($key, $value, HOUR_IN_SECONDS);

   return $value;
}
在您的私有站点中,使用这样的代码可以提高站点性能a lot, 尤其是如果你有很多用户。

请注意:

默认情况下,调试打开时不使用缓存,因此希望在您的开发环境中使用。相信我,缓存会让调试变成地狱。默认情况下,如果WP未设置为使用外部对象缓存,则也不会使用缓存。这意味着与MySQL相关的所有问题都不存在,因为您在使用MySQL时不使用瞬态。一个可能更容易的选择是使用wp_cache_* functions, 所以,如果没有设置外部缓存,那么缓存发生在内存中,而数据库永远不会涉及

  • 缓存的使用是可过滤的,要处理某些边缘情况,您可能会遇到没有网络规模的情况,如果没有缓存,则不应尝试解决缓存的速度问题。如果您有速度问题,那么您应该重新考虑您的代码。

    但要在webscale上扩展网站,缓存是非常有用的required.

    而且很多时候(但并非总是)片段化、上下文感知缓存比主动式全页缓存更加灵活和合适。

    您的问题是:

    我应该在这里使用瞬态API吗?

    It depends.

    您的代码是否消耗了大量资源?如果没有,可能不需要缓存。正如所说,这不仅仅是速度的问题。如果您的代码运行速度很快,但需要一堆CPU和内存供几个用户使用。。。当您有100或1000个并发用户时会发生什么情况?

    如果你意识到缓存是个好主意。。

    。。。这是公共代码:probably no. 您可以考虑有选择地缓存,就像我上面在公共代码中的示例一样,但如果将此类决策留给实现者,通常会更好。

    。。。并且是专用代码:very probably yes. 但即使对于私有代码,有选择地缓存仍然是一件好事,例如对于调试。

    无论如何,记住wp_cache_* 函数可以让您访问缓存,而不会有污染数据库的风险。

    我应该使用瞬态API缓存$related\\u posts数组还是$html\\u输出字符串?

    It depends 在很多事情上。绳子有多大?您正在使用哪个外部缓存?如果要缓存帖子,将ID存储为数组可能是一个好主意,通过ID查询大量帖子非常快。

    《最后的注释》瞬态API可能是WordPress最好的东西之一。由于您可以为任何类型的缓存系统找到插件,它成为了大量可以在引擎盖下工作的软件的一个愚蠢的简单API。

    在WordPress之外,很难找到这样的抽象,它可以与一系列不同的缓存系统一起开箱即用,并允许您毫不费力地从一个系统切换到另一个系统。

    你很少能听到我说WordPress比其他现代的东西更好,但当我不使用WordPress时,瞬态API是我错过的为数不多的事情之一。

    当然,缓存很难,不能解决代码问题,也不是一个灵丹妙药,但它是你需要的东西need 建立一个高流量的网站。

    WordPress使用未经优化的MySQL表进行缓存的想法非常疯狂,但仅仅因为WordPress在默认情况下进行了缓存,就让自己远离缓存并不是更好的选择。

    你只需要了解事情是如何运作的,然后做出选择。

  • SO网友:Alain Schlesser

    之前的回答已经强调了“必修课”It depends.“,对此我完全同意。

    不过,我想添加一条建议,根据我“假设”的方式,这最好在您上面描述的场景中完成。

    在这种情况下,我不会使用瞬态,而是使用后Meta,因为后者有一个优点:Control.

    由于需要按每篇文章缓存数据,因此要缓存的数据量取决于文章的数量,并且会随着时间的推移而增长。一旦超过一定数量的帖子,您可能会达到对象缓存允许使用的内存限制,并且它将在过期之前开始从内存中擦除以前缓存的数据。这可能会导致这样一种情况,即您有大量的访问者涌入,每个访问者都会在每个页面请求时触发“过于复杂的SQL”,您的站点将完全陷入困境。

    如果将数据缓存在Post Meta中,则不仅可以控制数据的存储和检索方式,还可以精确控制数据的更新方式。您将为此添加一个cron作业,该作业仅在站点流量较少或没有流量的时间段运行。因此,网站的真正用户永远不会遇到“慢查询”,您甚至可以预加载它,这样当第一个访问者点击时,工作就已经完成了。

    请记住,所有缓存都是一种权衡!这就是为什么通常的答案是“视情况而定”以及为什么没有“圣杯”。

    相关推荐

    Which cache is kicking

    我一直在为一个从另一个开发者那里继承下来的网站而挣扎。我的主要问题是,我在模板的css文件中所做的更改并没有立即得到响应,这表明某种缓存正在发挥作用。我检查的是。这个。任何缓存指令的htaccess文件</任何可能被激活的缓存WordPress插件</主机实现的任何缓存功能</Cloudflare或任何其他CDN</我尝试了不同的浏览器和计算机,所以缓存是服务器端的您可以想象,上面的任何一项都没有启用,但我对css的更改需要几个小时才能看到。我在任何方面都不是WordPress专家