问题描述

我正在寻找一个确定的答案。当启用对象缓存时,选项和瞬态在哪里最终生活?

默认情况下,两者都存储在数据库中。但是我听说过 memcache 会把它们存储在别的地方,APC 会完全做别的事情。在这两种情况下,这个数据究竟在哪里呢?

最佳解决方案

默认情况下,WordPress 是一种形式的”Object Caching”,但它的生命周期只有一个页面加载。

选项实际上是一个很好的例子。查看 this answer 了解更多信息。摘要:

  1. 页面开始

  2. 所有选项都加载了一个简单的 SELECT option_name, option_value from $wpdb->options 语句

  3. 对这些选项的后续请求 (例如,对 get_option 的调用从未打到数据库,因为它们与 WP 缓存 API 一起存储。

数据库中的选项总是”live”,并且始终保留在那里 – 这是他们的”canonical” 源。也就是说,选项被加载到对象缓存中,所以当您请求一个选项时,有 99%的机会,该请求永远不会打到数据库。

瞬态有些不同。

WordPress 允许您使用 drop-in(一个直接放置在 wp-content 文件夹中的文件) 来替换缓存 api 。如果您创建自己的缓存或使用 existing plugin,您可以使对象缓存持续时间超过单个页面加载时间。当你这样做,瞬变,改变一点。

我们来看看 wp-includes/option.php 中的 set_transient 功能。

<?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.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-includes/load.php 中的 wp_start_object_cache

<?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 。

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

简单。如果你需要数据的无限期延续,使用的选项。他们得到”cached”,但他们的典型来源是数据库,他们将永远不会消失,除非用户明确请求。

对于应该在一定时间内存储的数据,但不需要在指定的生命周期内持续使用瞬态。在内部,WP 将尝试使用一个外部的永久性对象缓存,否则数据将进入选项表,并在 WordPress’ psuedo-cron 到期时通过 WordPress’ psuedo-cron 获取垃圾。

一些其他问题/问题:

  1. get_option 进行大量呼叫可以吗?大概。它们引发了对函数开销的调用,但它可能不会打到数据库。数据库负载通常比 Web 应用程序可扩展性更重要,而不是您选择的语言生成页面的工作。

  2. 如何知道使用瞬态与 Cache API?如果您希望数据在一段时间内持续存在,请使用 transient API 。如果数据持续存在 (例如,计算/获取数据并不需要很长时间,但每次加载不应超过一次),请使用缓存 API 。

  3. 所有选项是否真正缓存在每个页面加载?不必要。如果您将 add_option 的最后一个可选参数称为 no,则它们不会自动加载。也就是说,一旦你抓取它们,他们进入缓存,后续的调用将不会打到数据库。

次佳解决方案

我知道有 4 种缓存类型

  1. 简单 – 在任何其他缓存发挥作用之前,它始终处于起作用。它将缓存的项目存储在 php 数组中,这意味着它从 PHP 执行会话中消耗内存,并且在 php 执行结束后缓存被清空。即使没有使用任何其他缓存,如果您连续两次调用 get_option(‘opt’),则只会在第一次进行 DB 查询,第二次将从内存返回该值。

  2. 文件 – 缓存的值存储在根目录下的文件中。我认为它证明在性能方面是无效的,除非你有一个非常快的磁盘或内存映射文件存储。

  3. APC(或其他基于 php 加速器的缓存) – 缓存值存储在主机的内存中,并且不在您的 php 内存分配之外。最大的潜在可怜的是,没有数据范围,如果您运行两个站点,每个站点都可以访问另一个的缓存数据,或者覆盖它。

  4. Memcahce – 它是一个基于网络的缓存。您可以在网络上的任何地方运行缓存服务,它可能会将值存储在主机内存中。你可能不需要 memcache,除非你有一个负载平衡的行动。

BTW,对象缓存是高速缓存的选项,它几乎可以存储使用高级 WP API 从数据库检索的任何东西。

参考文献

注:本文内容整合自 google/baidu/bing 翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:gxnotes#qq.com(#替换为 @) 。