How does object caching work?

时间:2012-12-02 作者:EAMann

我在这里寻找一个明确的答案。启用对象缓存后,选项和瞬变将在何处结束?

默认情况下,两者都存储在数据库中。但我听说memcache将把它们存储在其他地方,而APC将完全执行其他操作。在哪,这两种情况下都会保留此数据?

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

默认情况下,WordPress执行一种形式的“对象缓存”,但其生存期仅为单页加载。

选项实际上就是一个很好的例子。退房this answer 了解更多信息。总结:

页面开始时,所有选项都会加载一个简单的SELECT option_name, option_value from $wpdb->options 声明对这些选项的后续请求(例如get_option 永远不要访问数据库,因为它们是用WP缓存API存储的选项始终“存在”于数据库中,并始终保存在那里——这是它们的“规范”源。这就是说,选项会加载到对象缓存中,因此当您请求选项时,请求有99%的几率不会命中数据库。

瞬态有点不同。

WordPress允许您将缓存api替换为一个下拉菜单,该文件直接放置在wp-content 文件夹如果您创建自己的缓存拖放或使用existing plugin, 您可以使对象缓存的持续时间长于单个页面加载。当你这样做的时候,瞬变,改变一点。

让我们看看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将使用对象缓存而不是数据库来存储瞬态。那么,这是如何实现的呢?是时候探索一下WP如何设置自己的缓存API了。

你几乎可以追踪到wp-load.phpwp-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 为真。

如果您使用的是外部对象缓存,瞬态将使用它。这就提出了何时使用选项与瞬态的问题。

易于理解的如果需要数据无限期地持久化,请使用选项。它们被“缓存”,但它们的规范源是数据库,除非用户明确请求,否则它们永远不会消失。

对于应该存储一定时间,但不需要超过指定寿命的数据,请使用瞬态。在内部,如果可以的话,WP将尝试使用外部持久对象缓存,否则数据将进入选项表并通过WordPress\' psuedo-cron 当它们到期时。

其他一些关注/问题:

打很多电话给get_option?如果您希望数据在设定的时间段内保持不变,请使用瞬态API。如果数据是否持续存在无关紧要(例如,计算/获取数据不会花费很长时间,但每次页面加载不会发生多次),请使用缓存API不一定。如果你打电话add_option 最后一个可选参数为no 它们不是自动加载的。也就是说,一旦您提取它们一次,它们就会进入缓存,后续调用不会命中数据库

SO网友:Mark Kaplun

我知道有4种缓存类型

琐碎-它始终处于启用状态,并在任何其他缓存发挥作用之前生效。它将缓存的项目存储在php数组中,这意味着它会消耗php执行会话中的内存,并且在php执行结束后,缓存会被清空。i、 e.即使不使用任何其他缓存,如果您连续两次调用get\\u选项(“opt”),您将仅在第一次执行DB查询,第二次将从内存返回值。

文件-缓存的值存储在根目录下的文件中。我认为,除非您有非常快速的磁盘或内存映射文件存储,否则它在性能方面证明是无效的。

APC(或其他基于php加速器的缓存)—缓存的值存储在主机的内存中,不在php内存分配范围内。最大的潜在陷阱是没有数据的作用域,如果您运行两个站点,那么每个站点都可能访问另一个站点的缓存数据,或者覆盖它。

Memcache-它是一种基于网络的缓存。您可以在网络上的任何位置运行缓存服务,它可能会将值存储在其主机内存中。您可能不需要memcache,除非您正在进行负载平衡。

顺便说一句,对象缓存不仅仅是缓存选项,它将存储使用高级WP API从DB检索到的几乎所有内容。

SO网友:onetrickpony

选项始终存储在数据库中,而如果安装了APC和在WP中实现APC缓存的插件,则瞬态可能仅存储在共享内存中。Memcache也使用内存。

选项也存储在内存中,并在可能的情况下从内存中加载(如果没有,则执行db查询)。

SO网友:prosti

问得好。

我认为WordPress使用的部分WP_Object_Cache 类仍然缺失,因此我将添加它。

从文档中:

定义:WordPress对象缓存用于保存到数据库的行程。对象缓存将所有缓存数据存储到内存中,并通过使用键使缓存内容可用,该键用于命名缓存内容并在以后检索缓存内容。

这是WP_Object_Cache 结构

enter image description here

注+为公共、-私有、#保护。

您使用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 保存实际缓存数据。

在编程中,缓存结构无处不在。以简单的形式,它们可以被识别为键值对。bucket、NoDB结构、数据库索引。WordPress对象缓存的最终目标不是拥有尽可能简单的结构,但仍然可以识别键值对。

自从我在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
        )
对象将是值caching key 可能是

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:   }

结束

相关推荐

Bypassing a Form Options

情况是这样的。我正在使用一个插件,虽然它(一半)工作正常,但我无法访问设置页面。该插件是从Youtube和其他视频网站获取缩略图,但问题是,出于审美原因,我必须使用特定的“特色”框嵌入视频。如果我按照“通常的方式”将视频放在帖子中,效果会很好。我做了一些研究,显然插件接受自定义字段值(这可以解决我的问题),但我必须在其设置页面中输入自定义字段名称。由于某种原因,我无法访问它,只能得到一个空白页。我认为这可能是插件冲突,但我尝试过激活和停用其他插件,但仍然没有成功。我查看代码,发现这部分:<th sc