默认情况下,两者都存储在数据库中。但是我听说一些参考资料称Memcache会将它们存储在其他位置,而APC将完全做其他事情。两种情况下,这些数据究竟将保留在什么地方?
#1 楼
WordPress默认情况下会执行“对象缓存”的形式,但其生存期仅为一次页面加载。选项实际上是一个很好的例子。查看此答案以获取更多信息。摘要:
页面开始
所有选项均加载有简单的
SELECT option_name, option_value from $wpdb->options
语句随后对这些选项的请求(例如,对
get_option
的调用从未命中数据库因为它们是用WP缓存API存储的。选项始终在数据库中“活动”并始终存在于数据库中-这就是它们的“规范”源。也就是说,选项已加载到对象缓存中因此,当您请求一个选项时,请求有99%的可能性将永远不会到达数据库。瞬态有些不同。插件-直接放置在您的
wp-content
文件夹中的文件。如果您创建自己的缓存插件或使用现有插件,则可以使对象缓存的保存时间长于单个页面加载的时间。 让我们看一下
set_transient
中的wp-includes/option.php
函数。<?php
/**
* Set/update the value of a transient.
*
* You do not need to serialize values. If the value needs to be serialized, then
* it will be serialized before it is set.
*
* @since 2.8.0
* @package WordPress
* @subpackage Transient
*
* @uses apply_filters() Calls 'pre_set_transient_$transient' hook to allow overwriting the
* transient value to be stored.
* @uses do_action() Calls 'set_transient_$transient' and 'setted_transient' hooks on success.
*
* @param string $transient Transient name. Expected to not be SQL-escaped.
* @param mixed $value Transient value. Expected to not be SQL-escaped.
* @param int $expiration Time until expiration in seconds, default 0
* @return bool False if value was not set and true if value was set.
*/
function set_transient( $transient, $value, $expiration = 0 ) {
global $_wp_using_ext_object_cache;
$value = apply_filters( 'pre_set_transient_' . $transient, $value );
if ( $_wp_using_ext_object_cache ) {
$result = wp_cache_set( $transient, $value, 'transient', $expiration );
} else {
$transient_timeout = '_transient_timeout_' . $transient;
$transient = '_transient_' . $transient;
if ( false === get_option( $transient ) ) {
$autoload = 'yes';
if ( $expiration ) {
$autoload = 'no';
add_option( $transient_timeout, time() + $expiration, '', 'no' );
}
$result = add_option( $transient, $value, '', $autoload );
} else {
if ( $expiration )
update_option( $transient_timeout, time() + $expiration );
$result = update_option( $transient, $value );
}
}
if ( $result ) {
do_action( 'set_transient_' . $transient );
do_action( 'setted_transient', $transient );
}
return $result;
}
嗯
$_wp_using_ext_object_cache
吗?是的,WordPress使用对象缓存而不是数据库来存储瞬态。那么如何将其设置为true?是时候探索WP如何设置其自己的缓存API。您几乎可以将所有内容都跟踪到
wp-load.php
或wp-settings.php
,这两者都是WordPress引导过程的关键。在我们的缓存中,wp-settings.php
中有一些相关的行。// Start the WordPress object cache, or an external object cache if the drop-in is present.
wp_start_object_cache();
还记得从上面掉下来的东西吗?让我们看一下
wp_start_object_cache
中的wp-includes/load.php
。<?php
/**
* Starts the WordPress object cache.
*
* If an object-cache.php file exists in the wp-content directory,
* it uses that drop-in as an external object cache.
*
* @access private
* @since 3.0.0
*/
function wp_start_object_cache() {
global $_wp_using_ext_object_cache, $blog_id;
$first_init = false;
if ( ! function_exists( 'wp_cache_init' ) ) {
if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
require_once ( WP_CONTENT_DIR . '/object-cache.php' );
$_wp_using_ext_object_cache = true;
} else {
require_once ( ABSPATH . WPINC . '/cache.php' );
$_wp_using_ext_object_cache = false;
}
$first_init = true;
} else if ( !$_wp_using_ext_object_cache && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
// Sometimes advanced-cache.php can load object-cache.php before it is loaded here.
// This breaks the function_exists check above and can result in $_wp_using_ext_object_cache
// being set incorrectly. Double check if an external cache exists.
$_wp_using_ext_object_cache = true;
}
// If cache supports reset, reset instead of init if already initialized.
// Reset signals to the cache that global IDs have changed and it may need to update keys
// and cleanup caches.
if ( ! $first_init && function_exists( 'wp_cache_switch_to_blog' ) )
wp_cache_switch_to_blog( $blog_id );
else
wp_cache_init();
if ( function_exists( 'wp_cache_add_global_groups' ) ) {
wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache' ) );
wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
}
}
函数的相关行(与
$_wp_using_ext_object_cache
有关的行更改了瞬态的存储方式)。 > if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
require_once ( WP_CONTENT_DIR . '/object-cache.php' );
$_wp_using_ext_object_cache = true;
} else {
require_once ( ABSPATH . WPINC . '/cache.php' );
$_wp_using_ext_object_cache = false;
}
如果内容目录中存在
object-cache.php
,它将包含在内,并且WP假定您正在使用外部持久性缓存-它将$_wp_using_ext_object_cache
设置为true。如果您使用的是外部对象缓存,则瞬态将使用它。这就提出了何时使用选项与瞬态的问题。
简单。如果需要数据无限期地保留,请使用选项。它们被“缓存”,但是它们的规范来源是数据库,除非用户明确请求,否则它们永远不会消失。
对于应该存储一定时间的数据,但不会存储需要持续超过指定的生命周期使用瞬态。在内部,如果可能,WP将尝试使用外部的持久对象缓存,否则数据将进入选项表,并在过期时通过WordPress的psuedo-cron收集垃圾。
其他一些担忧/问题:
可以无数次拨打
get_option
吗?大概。他们招致了函数开销的调用,但是它可能不会访问数据库。与您选择的语言生成页面所做的工作相比,数据库负载通常是Web应用程序可伸缩性中更大的问题。我如何知道使用瞬态与Cache API?如果您希望数据在设定的时间内持续存在,请使用瞬时API。如果数据是否持久无关紧要(例如,计算/获取数据不会花费很长时间,但是每次页面加载它都不会发生多次),请使用缓存API。
所有选项真的都缓存在每个页面加载上吗?不必要。如果使用最后一个可选参数
add_option
调用no
,则不会自动加载它们。也就是说,一旦提取它们一次,它们就会进入缓存,后续调用将不会到达数据库。评论
nitpick 1:并非所有选项都在页面开始时加载,只有那些在创建时标记为“ autoload = yes”的选项。 add_option中该参数的默认值为“是”,并且大多数插件编写者都不会理会使用“否”的区别,在那里您的陈述实际上是正确的。
–马克·卡普伦
2012年12月3日,下午5:32
即使非自动加载的选项在被提取一次之后也会被缓存。它们可能最初并未加载,但之后确实会进入对象缓存。甚至不存在的选项也会被缓存! github.com/WordPress/WordPress/blob/master/wp-includes/…但是,我添加了有关自动加载选项的注释。
–chrisguitarguy
2012年12月3日5:37
那是nitpick 2;)
–马克·卡普伦
2012年12月3日,下午5:42
感谢您的精彩文章,以及所有这些内容的总结。
–prosti
16 Dec 15'在13:54
多棒的有用答案,谢谢!
–最后
20年6月11日在8:42
#2 楼
我知道有4种缓存类型Trivial-它始终启用并在其他任何缓存开始起作用之前起作用。它将缓存的项目存储在php数组中,这意味着它从php执行会话中消耗了内存,并且在php执行结束后清空了缓存。即,即使不使用任何其他缓存,如果连续两次调用get_option('opt'),则将仅在第一次和第二次从内存中返回该值时才进行数据库查询。
文件-缓存的值存储在根目录下某处的文件中。我认为,除非您拥有非常快速的磁盘或内存映射文件存储,否则它在性能方面是无效的。
APC(或其他基于PHP加速器的缓存)-缓存的值存储在主机的内存中和您的PHP内存分配之外。最大的潜在陷阱是没有数据作用域,如果您运行两个站点,则每个站点都可能可以访问另一个站点的缓存数据或将其覆盖。
Memcache-它是基于网络的缓存。您可以在网络上的任何地方运行缓存服务,它可能会将值存储在其主机内存中。除非您进行负载平衡,否则您可能不需要内存缓存。
BTW,对象缓存比选项缓存要多得多,它几乎可以存储使用高级WP从数据库检索到的所有内容。 API。
评论
我知道答案是相当古老的,但我还要添加出色的Redis。
–Cranio
16年4月12日在10:32
@Cranio,您是对的,但是... redis本质上是带有存储的内存缓存的变体,因此它是(NoSQL)DB。这个IMHO实际上很糟糕,好像该节点发生故障或无法更新一样,您可能会从中获取陈旧的信息。它有一个选项可以关闭类似DB的行为,但是我不确定默认情况下它是打开还是关闭。
–马克·卡普伦
16年4月12日在10:42
它是Memcached(甚至更好)的完美替代品,您还需要什么?到目前为止,我所见过的最普通的用法就是将其作为RAM键值存储(是的,除此之外,可以使数据持久化,集群正在运行并且具有队列管理功能,但是每个人都认为Redis是出色的WP的缓存选项)
–Cranio
16年4月12日在12:45
每个人都可以跳桥;),但是完全不需要增加缓存的复杂性
–马克·卡普伦
16年4月12日在13:04
那是完全没有意义的。您要RAM缓存,Redis进行RAM缓存,周期;它做的很棒。如果您不想这样做,绝对不会增加任何复杂性。所以,先生,我真的不明白你的意思。
–Cranio
16年4月13日在10:41
#3 楼
选项始终存储在数据库中,而瞬变仅在安装了APC和在WP中实现APC缓存的插件时才可能存储在共享内存中。 Memcache也会使用内存。选项也存储在内存中,并在可能的情况下从那里加载(如果没有,则执行db查询)。
#4 楼
很好的问题。我认为仍然缺少WordPress如何使用
WP_Object_Cache
类的部分,因此我将其添加。来自文档:
DEF:WordPress对象缓存用于保存对数据库的旅行。对象缓存将所有缓存数据存储到内存中,并通过使用密钥来使缓存内容可用,该密钥用于命名和稍后检索缓存内容。这是
WP_Object_Cache
结构。注意+是公共的,-私有的,#受保护的。显示有关全局缓存对象及其中内容的常规统计信息的方法。输出为:
Cache Hits: 110
Cache Misses: 98
Group: options - ( 81.03k )
Group: default - ( 0.03k )
Group: users - ( 0.41k )
Group: userlogins - ( 0.03k )
Group: useremail - ( 0.04k )
Group: userslugs - ( 0.03k )
Group: user_meta - ( 3.92k )
Group: posts - ( 1.99k )
Group: terms - ( 1.76k )
Group: post_tag_relationships - ( 0.04k )
Group: category_relationships - ( 0.03k )
Group: post_format_relationships - ( 0.02k )
Group: post_meta - ( 0.36k )
这是我在模板
stats()
之类的开头就得到的内容。请注意变量我们感兴趣的是:
single.php
。私有成员
global $wp_object_cache
保存实际的缓存数据。在编程中,缓存结构无处不在。以简单的形式,它们可以被识别为键值对。值区,NoDB结构,数据库索引。 WordPress对象缓存的最终目标不是拥有尽可能简单的结构,而是仍然可以识别键值对。
由于打印缓存时我在
$cache
中,所以我print_r($wp_object_cache->cache['posts']);
我正在缓存单个帖子。
[last_changed] => 0.34169600 1481802075
[get_page_by_path:2516f01e446b6c125493ec7824b63868:0.34169600 1481802075] => 0
[2831] => WP_Post Object
(
[ID] => 2831
[post_author] => 1
... the cached post object goes here
)
对象将是值,而缓存键将是be
get_page_by_path:2516f01e446b6c125493ec7824b63868:0.34169600 1481802075
在这里,您可以检查
single.php
的结构:File: /wp-includes/post.php
4210: /**
4211: * Retrieves a page given its path.
4212: *
4213: * @since 2.1.0
4214: *
4215: * @global wpdb $wpdb WordPress database abstraction object.
4216: *
4217: * @param string $page_path Page path.
4218: * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
4219: * a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.
4220: * @param string|array $post_type Optional. Post type or array of post types. Default 'page'.
4221: * @return WP_Post|array|null WP_Post (or array) on success, or null on failure.
4222: */
4223: function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {
4224: global $wpdb;
4225:
4226: $last_changed = wp_cache_get_last_changed( 'posts' );
4227:
4228: $hash = md5( $page_path . serialize( $post_type ) );
4229: $cache_key = "get_page_by_path:$hash:$last_changed";
4230: $cached = wp_cache_get( $cache_key, 'posts' );
4231: if ( false !== $cached ) {
4232: // Special case: '0' is a bad `$page_path`.
4233: if ( '0' === $cached || 0 === $cached ) {
4234: return;
4235: } else {
4236: return get_post( $cached, $output );
4237: }
4238: }
评论
@toscho提到的文章现在可以在archive.org上找到:探索WordPress Cache API