問題描述

我正在尋找一個確定的答案。當啟用物件快取時,選項和瞬態在哪裡最終生活?

預設情況下,兩者都儲存在資料庫中。但是我聽說過 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(#替換為 @) 。