Bagaimana cara kerja caching objek?

21

Saya mencari jawaban yang pasti di sini. Ketika cache objek diaktifkan, di mana opsi dan transien berakhir hidup?

Secara default, keduanya disimpan dalam database. Tetapi saya telah mendengar beberapa referensi bahwa memcache akan menyimpannya di tempat lain dan APC akan melakukan sesuatu yang lain sama sekali. Dimana, tepatnya , apakah data ini akan bertahan dalam kedua kasus?

EAMann
sumber
2
Artikel @toscho menyebutkan sekarang tersedia di archive.org: Menjelajahi WordPress Cache API
sini

Jawaban:

34

WordPress, secara default, melakukan bentuk "Object Caching" tetapi masa pakainya hanya satu halaman.

Opsi sebenarnya adalah contoh yang sangat bagus untuk ini. Lihatlah jawaban ini untuk info lebih lanjut. Ringkasan:

  1. Halaman dimulai
  2. Semua opsi dimuat dengan SELECT option_name, option_value from $wpdb->optionspernyataan sederhana
  3. Permintaan selanjutnya untuk opsi-opsi tersebut (mis. Panggilan untuk get_optiontidak pernah menekan database karena disimpan dengan API cache WP.

Opsi selalu "hidup" dalam database dan selalu bertahan di sana - itulah sumber "kanonik" mereka. Yang mengatakan, opsi dimuat ke dalam objek cache sehingga ketika Anda meminta opsi ada kemungkinan 99% bahwa permintaan tidak akan pernah mencapai database.

Transien sedikit berbeda.

WordPress memungkinkan Anda untuk mengganti api cache dengan drop-in - file yang ditempatkan langsung di wp-contentfolder Anda . Jika Anda membuat cache sendiri, drop in atau gunakan plugin yang ada , Anda dapat membuat cache objek bertahan lebih lama dari satu pemuatan halaman. Ketika Anda melakukan itu, transien, ubah sedikit.

Mari kita lihat set_transientfungsi di 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;
}

Hmmm $_wp_using_ext_object_cache? Jika itu benar, WordPress menggunakan objek cache bukan database untuk menyimpan transien. Jadi bagaimana itu bisa menjadi kenyataan? Saatnya mengeksplorasi bagaimana WP mengatur API cache-nya sendiri.

Anda dapat melacak hampir semua hal untuk wp-load.phpatau wp-settings.php- keduanya penting untuk proses bootstrap WordPress. Di cache kami, ada beberapa baris yang relevan di wp-settings.php.

// Start the WordPress object cache, or an external object cache if the drop-in is present.
wp_start_object_cache();

Ingat barang drop-in dari atas? Mari kita lihat wp_start_object_cachedi 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' ) );
    }
}

Baris fungsi yang relevan (yang berkaitan dengan $_wp_using_ext_object_cacheitu mengubah cara transien disimpan).

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

jika object-cache.phpada di direktori konten Anda akan disertakan dan WP menganggap Anda menggunakan cache eksternal yang persisten - disetel $_wp_using_ext_object_cacheke true.

Jika Anda menggunakan transien objek cache eksternal akan menggunakannya. Yang memunculkan pertanyaan kapan harus menggunakan opsi vs transien.

Sederhana. Jika Anda membutuhkan data untuk bertahan tanpa batas waktu, gunakan opsi. Mereka mendapatkan "cache", tetapi sumber kanonik mereka adalah database dan mereka tidak akan pernah pergi kecuali jika pengguna secara eksplisit memintanya.

Untuk data yang harus disimpan untuk jangka waktu tertentu, tetapi tidak perlu bertahan selama transien penggunaan seumur hidup yang ditentukan. Secara internal, WP akan mencoba menggunakan cache objek eksternal yang persisten, jika tidak, maka data akan masuk ke tabel opsi dan mengumpulkan sampah melalui psuedo-cron WordPress. ketika mereka kedaluwarsa.

Beberapa masalah / pertanyaan lain:

  1. Apakah saya tetap bisa melakukan banyak panggilan get_option?Mungkin. Mereka membuat panggilan ke fungsi overhead, tetapi kemungkinan tidak akan mencapai basis data. Pemuatan basis data sering kali merupakan masalah yang lebih besar dalam skalabilitas aplikasi web daripada pekerjaan yang dipilih oleh bahasa pilihan Anda.
  2. Bagaimana saya tahu menggunakan transien vs. API Cache? Jika Anda mengharapkan data bertahan selama periode yang ditentukan, gunakan API sementara. Jika tidak masalah jika data tetap ada (mis. Tidak butuh waktu lama untuk menghitung / mengambil data, tetapi seharusnya tidak terjadi lebih dari satu kali per pemuatan halaman) menggunakan API cache.
  3. Apakah semua opsi benar-benar di-cache pada setiap pageload? Belum tentu. Jika Anda menelepon add_optiondengan argumen terakhir, opsional karena notidak diisi secara otomatis. Yang mengatakan, sekali Anda mengambilnya sekali, mereka masuk ke cache dan panggilan berikutnya tidak akan mencapai database.
chrisguitarguy
sumber
nitpick 1: Tidak semua opsi dimuat di awal halaman, tetapi hanya yang ditandai "autoload = yes" saat dibuat. Default untuk parameter di add_option adalah 'ya' dan kebanyakan penulis plugin tidak repot-repot memahami perbedaan dalam menggunakan 'tidak' di sana membuat pernyataan Anda praktis benar.
Mark Kaplun
Bahkan opsi yang tidak dimuat secara otomatis di-cache setelah diambil satu kali. Mereka mungkin tidak dimuat pada awalnya, tetapi mereka masuk ke cache objek setelah itu. Bahkan opsi yang tidak ada di-cache! github.com/WordPress/WordPress/blob/master/wp-includes/... Saya menambahkan catatan tentang opsi pengisian otomatis.
chrisguitarguy
itu nitpick 2;)
Mark Kaplun
Terima kasih atas artikelnya yang luar biasa, dan atas waktunya merangkum semua itu.
prosti
5

Ada 4 jenis cache yang saya ketahui

  1. Trivial - Selalu aktif dan berpengaruh sebelum caching lainnya ikut bermain. Ia menyimpan item yang di-cache dalam array php yang berarti bahwa ia menghabiskan memori dari sesi eksekusi php Anda, dan bahwa cache dikosongkan setelah eksekusi php selesai. yaitu bahkan tanpa menggunakan cache lain jika Anda memanggil get_option ('opt') dua kali berturut-turut, Anda akan membuat permintaan DB hanya pertama kali dan kedua kalinya nilainya akan dikembalikan dari memori.

  2. File - Nilai cache disimpan dalam file di suatu tempat di bawah direktori root Anda. Saya percaya ini terbukti tidak efektif dalam hal kinerja kecuali Anda memiliki disk yang sangat cepat atau penyimpanan file yang dipetakan.

  3. APC (atau cache berbasis akselerator php lainnya) - Nilai cache disimpan dalam memori mesin host Anda dan di luar alokasi memori php Anda. Jebakan potensial terbesar adalah tidak ada ruang lingkup data dan jika Anda menjalankan dua situs yang berpotensi masing-masing dapat mengakses data yang di-cache dari yang lain, atau menimpanya.

  4. Memcache - ini adalah cache berbasis jaringan. Anda dapat menjalankan layanan caching di mana saja di jaringan dan Ini mungkin menyimpan nilai dalam memori hostnya. Anda mungkin tidak perlu memcache kecuali Anda sedang melakukan load balancing.

BTW, objek caching adalah caching lebih dari pilihan, ia akan menyimpan hampir semua yang diambil dari DB menggunakan WP API tingkat tinggi.

Mark Kaplun
sumber
Saya tahu jawabannya cukup lama, tetapi saya akan menambahkan juga Redis yang sangat baik .
Cranio
@Cranio, Anda benar tapi ... redis pada dasarnya adalah varian dari memcache dengan penyimpanan, dan karenanya itu adalah DB (NoSQL). IMHO ini sebenarnya buruk seolah-olah simpul gagal atau tidak dapat diperbarui Anda mungkin mendapatkan info basi dari itu. Ini memiliki opsi untuk mematikan perilaku seperti DB tetapi saya tidak yakin apakah itu hidup atau mati secara default.
Mark Kaplun
Ini adalah pengganti sempurna untuk Memcached (bahkan lebih baik), apa lagi yang Anda butuhkan? Sejauh ini, penggunaan paling umum yang saya lihat hanyalah sebagai penyimpanan nilai kunci RAM (ya, selain itu, data dapat dibuat tetap, pengelompokan sedang berlangsung, dan memiliki kemampuan manajemen antrian, tetapi semua orang menambahkan Redis sebagai yang terbaik opsi caching untuk WP)
Cranio
semua orang juga dapat melompat dari jembatan;) tetapi kompleksitas yang ditambahkan sama sekali tidak diperlukan untuk caching
Mark Kaplun
Sama sekali tidak ada gunanya; Anda ingin caching RAM, Redis melakukan caching RAM, titik; dan itu melakukannya dengan luar biasa. Sama sekali tidak ada kerumitan tambahan jika Anda tidak ingin melakukannya. Jadi, Tuan, saya benar-benar gagal memahami maksud Anda.
Cranio
0

Opsi selalu disimpan dalam database, sementara transien dapat disimpan hanya dalam memori bersama jika APC dan plugin yang mengimplementasikan caching APC di WP diinstal. Memcache juga menggunakan memori.

Opsi juga disimpan dalam memori, dan dimuat dari sana jika memungkinkan (jika tidak, permintaan db dilakukan).

onetrickpony
sumber
0

Pertanyaan bagus

Saya pikir bagian dengan bagaimana WordPress menggunakan WP_Object_Cachekelas masih hilang, jadi saya akan menambahkannya.

Dari dokumen:

DEF: Cache Objek WordPress digunakan untuk menghemat perjalanan ke database. Object Cache menyimpan semua data cache ke memori dan membuat konten cache tersedia dengan menggunakan kunci, yang digunakan untuk memberi nama dan kemudian mengambil konten cache.

Ini WP_Object_Cachestrukturnya.

masukkan deskripsi gambar di sini

Note + bersifat publik, - pribadi, # dilindungi.

Anda menggunakan stats()metode ini untuk menampilkan statistik umum tentang objek cache global dan apa yang ada di sana. Berikut ini hasilnya:

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 )

Inilah yang saya dapatkan sebelumnya di awal template seperti single.php.

Perhatikan variabel yang kami minati adalah: global $wp_object_cache .

Pribadi anggota $cachememegang data caching yang sebenarnya.

Dalam pemrograman, struktur cache ada di mana-mana. Dalam bentuk sederhana mereka dapat dikenali sebagai pasangan nilai kunci. Bucket, struktur NoDB, indeks basis data. Tujuan akhir WordPress Object Cache bukanlah untuk memiliki struktur sesederhana mungkin, tetapi pasangan nilai kunci tetap dapat dikenali.

Sejak saya masuk single.phpketika saya mencetak cache:

print_r($wp_object_cache->cache['posts']);

Saya mendapatkan satu posting di-cache.

    [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
        )

Objek akan menjadi nilainya, dan kunci caching akan menjadi

get_page_by_path:2516f01e446b6c125493ec7824b63868:0.34169600 1481802075

Di sini Anda dapat memeriksa $cache_keystruktur:

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