Answers:
WordPress默认情况下会执行“对象缓存”的形式,但其生存期仅为一次页面加载。
选项实际上是一个很好的例子。查看此答案以获取更多信息。摘要:
SELECT option_name, option_value from $wpdb->options
语句get_option
从不打入数据库的调用,因为它们与WP缓存API一起存储。选项始终“活跃”在数据库中,并且始终存在于数据库中-这就是它们的“规范”来源。就是说,选项已加载到对象缓存中,因此当您请求选项时,有99%的可能性该请求将永远不会到达数据库。
瞬态有些不同。
WordPress允许你用替换缓存API 插入式 -一个文件,该文件被直接放在你的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应用程序可伸缩性中更大的关注点。add_option
使用其最后一个可选参数进行调用,因为no
它们不会自动加载。也就是说,一旦提取它们一次,它们就会进入缓存,后续调用将不会到达数据库。我知道有4种缓存类型
琐碎-它始终处于启用状态,并在其他任何缓存起作用之前起作用。它将缓存的项目存储在php数组中,这意味着它会占用php执行会话中的内存,并且在php执行结束后清空缓存。即,即使不使用任何其他缓存,如果您连续两次调用get_option('opt'),也只会在第一次和第二次从内存返回值时进行数据库查询。
文件-缓存的值存储在根目录下某个位置的文件中。我相信,除非您拥有非常快的磁盘或内存映射文件存储,否则就性能而言,它是无效的。
APC(或其他基于php加速器的缓存)-缓存的值存储在主机的内存中,而不在php内存分配中。最大的潜在陷阱是没有数据作用域,如果您运行两个站点,则每个站点都可能访问另一个站点的缓存数据或将其覆盖。
Memcache-它是基于网络的缓存。您可以在网络上的任何地方运行缓存服务,它可能会将值存储在其主机内存中。除非您具有负载平衡功能,否则您可能不需要内存缓存。
顺便说一句,对象缓存比选项缓存要多得多,它几乎可以存储使用高级WP API从数据库检索到的所有内容。
好问题。
我认为WordPress如何使用的部分 WP_Object_Cache
类的部分仍然缺失,因此我将其添加。
从文档:
DEF:WordPress对象缓存用于保存对数据库的旅行。对象缓存将所有缓存数据存储到内存中,并通过使用密钥来使缓存内容可用,该密钥用于命名和稍后检索缓存内容。
这是WP_Object_Cache
结构。
注意+是公开的,-是私有的,#受保护。
您可以使用该stats()
方法显示有关全局缓存对象及其中内容的常规统计信息。这是输出:
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 )
这是我在模板开始时所获得的(例如)single.php
。
注意我们感兴趣的变量是:
global $wp_object_cache
。
私有成员$cache
拥有实际的缓存数据。
在编程中,缓存结构无处不在。以简单的形式,它们可以被识别为键值对。值区,NoDB结构,数据库索引。WordPress Object Cache的最终目标不是拥有最简单的结构,而是仍然可以识别键值对。
由于我是在single.php
打印缓存时进入的:
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
)
该对象将是值,而缓存键将是
get_page_by_path:2516f01e446b6c125493ec7824b63868:0.34169600 1481802075
在这里,您可以检查$cache_key
结构:
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: }