オブジェクトキャッシュはどのように機能しますか?


21

ここで決定的な答えを探しています。オブジェクトのキャッシュが有効になっている場合、オプションとトランジェントはどこに住んでいますか?

デフォルトでは、両方がデータベースに保存されます。しかし、memcacheが他の場所にそれらを保存し、APCがまったく別のことを行うという参照を聞いたことがあります。正確に、どちらの場合でもこのデータはどこに保持されますか?


2
@toschoが言及した記事がarchive.orgで
ここでは

回答:


34

WordPressは、デフォルトで「オブジェクトキャッシュ」の形式を実行しますが、その有効期間は1ページのロードのみです。

オプションは実際にこれの実に良い例です。詳細については、この回答をご覧ください。サマリー:

  1. ページが始まります
  2. すべてのオプションは単純なSELECT option_name, option_value from $wpdb->optionsステートメントでロードされます
  3. これらのオプションに対する後続のリクエスト(たとえばget_option、WPキャッシュAPIで保存されているため、データベースにヒットしない呼び出し)。

オプションは常にデータベースに「ライブ」され、常にそこに永続化されます。それが「標準的な」ソースです。ただし、オプションはオブジェクトキャッシュに読み込まれるため、オプションを要求すると、99%の確率でその要求がデータベースにヒットしない可能性があります。

トランジェントは少し異なります。

WordPressでは、キャッシュAPIをドロップイン(wp-contentフォルダーに直接配置されるファイル)に置き換えることができます。独自のキャッシュドロップを作成するか、既存の プラグインを使用する場合、1ページのロードよりも長くオブジェクトキャッシュを保持できます。それを行うと、トランジェントが少し変わります。

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?trueの場合、WordPressはデータベースの代わりにオブジェクトキャッシュを使用してトランジェントを保存します。では、どのようにtrueに設定しますか?WPが独自のキャッシュAPIを設定する方法を探る時間です。

あなたはにほとんどすべてを追跡することができるwp-load.phpか、wp-settings.phpワードプレスのブートストラッププロセスに重要であるどちらも- 。キャッシュには、に関連する行がいくつかあります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で有効期限が切れたときにガベージコレクションが行われます。

その他の懸念事項/質問:

  1. 大量に電話しても大丈夫get_optionですか?多分。関数のオーバーヘッドが発生しますが、データベースにはヒットしません。多くの場合、データベースの負荷は、選択した言語でページを生成する作業よりも、Webアプリケーションのスケーラビリティにおいて大きな懸念事項です。
  2. トランジェントとキャッシュAPIを使用する方法を知るにはどうすればよいですか?データが一定期間持続すると予想される場合は、一時APIを使用します。データが持続するかどうかが問題でない場合(たとえば、データの計算/フェッチに時間がかからないが、ページの読み込みごとに複数回発生するべきではない)キャッシュAPIを使用します。
  3. すべてのオプションはすべてのページロードで実際にキャッシュされますか?必ずしも。オートロードされないためadd_option、最後のオプションの引数で呼び出す場合no。ただし、一度フェッチすると、キャッシュに入れられ、以降の呼び出しはデータベースにヒットしません。

nitpick 1:ページの開始時にすべてのオプションがロードされるわけではなく、作成時に「autoload = yes」とマークされているオプションのみがロードされます。add_optionのそのパラメーターのデフォルトは「yes」であり、ほとんどのプラグイン作成者は、「no」を使用することの違いを理解することを気にせず、ステートメントを実質的に真にします。
マークカプルン

自動ロードされていないオプションでさえ、一度フェッチされるとキャッシュされます。最初はロードされない場合がありますが、その後オブジェクトキャッシュに移動します。存在しないオプションもキャッシュされます!github.com/WordPress/WordPress/blob/master/wp-includes/…autoloadオプションに関するメモを追加しました。
chrisguitarguy

nitpick 2としたこと;)
マークKaplun

すばらしい記事をありがとう、そしてすべてを要約してくれてありがとう。
prosti

5

私が知っている4つのキャッシュタイプがあります

  1. 自明-これは常にオンであり、他のキャッシュが作用する前に有効になります。キャッシュされたアイテムをphp配列に保存します。つまり、php実行セッションからメモリを消費し、phpの実行が終了するとキャッシュが空になります。つまり、他のキャッシュを使用せずにget_option( 'opt')を2回続けて呼び出す場合でも、メモリから値が返されるのは1回目と2回目のDBクエリのみです。

  2. ファイル-キャッシュされた値は、ルートディレクトリの下のどこかのファイルに保存されます。非常に高速なディスクまたはメモリにマップされたファイルストレージがない限り、パフォーマンスの点で効果的でないことがわかったと思います。

  3. APC(または他のphpアクセラレータベースのキャッシュ)-キャッシュされた値は、ホストマシンのメモリとphpメモリ割り当ての外部に保存されます。潜在的な最大の落とし穴は、データのスコープがないことであり、2つのサイトを実行すると、それぞれが他方のキャッシュデータにアクセスしたり、上書きしたりする可能性があります。

  4. Memcache-ネットワークベースのキャッシュです。キャッシングサービスはネットワーク上のどこでも実行でき、おそらくホストメモリに値を保存します。負荷分散を実行していない限り、おそらくmemcacheは必要ありません。

ところで、オブジェクトキャッシングはオプションよりもはるかに多くをキャッシングしているため、高レベルのWP APIを使用してDBから取得したほぼすべてのものを保存します。


答えはかなり古いものですが、優れたRedisも追加します。
クラニオ

@Cranio、あなたは正しいですが... redisは基本的にストレージを備えたmemcacheのバリアントであり、そのため(NoSQL)DBです。このIMHOは、ノードに障害が発生した場合や更新できない場合に、古い情報を取得する可能性があるため、実際には不良です。DBのような動作をオフにするオプションがありますが、デフォルトでオンかオフかはわかりません。
マークカプルン

Memcachedの完全な代替品(さらに良い)ですが、他に何が必要ですか?私が見てきた最も一般的な使用法は、RAMキーと値のストレージとしてです(それ以外は、データを永続化でき、クラスタリングが進行中で、キュー管理機能がありますが、誰もがRedisを優れたものとして追加していますWPのキャッシュオプション)
Cranio

)が、追加複雑さは全くキャッシングは必要ありません。誰も橋のジャンプすることができます
マーク・Kaplun

それは完全に無意味です。RAMキャッシュが必要な場合、RedisはRAMキャッシュ期間を行います。そしてそれは素晴らしくそれをします。そこ絶対に何もあなたはそれのために行くにしたくない場合は複雑さを加えられていません。それで、先生、あなたの主張を本当に理解できません。
クラニオ

0

オプションは常にデータベースに保存されますが、APCおよびWPでAPCキャッシングを実装するプラグインがインストールされている場合、一時メモリは共有メモリにのみ保存されます。Memcacheもメモリを使用します。

オプションもメモリに保存され、可能な場合はそこからロードされます(そうでない場合、dbクエリが実行されます)。


0

いい質問ですね。

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:   }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.