การแคชวัตถุทำงานอย่างไร


21

ฉันกำลังมองหาคำตอบที่ชัดเจนที่นี่ เมื่อเปิดใช้งานการแคชวัตถุตัวเลือกและทรานแซคชันจะอยู่ที่ไหน

โดยค่าเริ่มต้นทั้งสองจะถูกเก็บไว้ในฐานข้อมูล แต่ฉันได้ยินการอ้างอิงบางอย่างที่ memcache จะเก็บไว้ที่อื่นและ APC จะทำอย่างอื่นโดยสิ้นเชิง ที่ว่าจะข้อมูลนี้ได้รับการยืนยันในทั้งสองกรณี?


2
ตอนนี้บทความ @toscho กล่าวถึงมีอยู่ในarchive.org: การสำรวจ WordPress Cache API
ที่นี่

คำตอบ:


34

โดยค่าเริ่มต้น WordPress ทำรูปแบบของ "การแคชวัตถุ" แต่อายุการใช้งานของมันนั้นเป็นเพียงการโหลดหน้าเดียว

ตัวเลือกเป็นตัวอย่างที่ดีของเรื่องนี้ ลองอ่านคำตอบนี้สำหรับข้อมูลเพิ่มเติม สรุป:

  1. หน้าเริ่มต้น
  2. ตัวเลือกทั้งหมดจะถูกโหลดด้วยSELECT option_name, option_value from $wpdb->optionsคำสั่งง่ายๆ
  3. คำขอครั้งต่อ ๆ มาสำหรับตัวเลือกเหล่านั้น (เช่นการเรียกใช้เพื่อget_optionไม่ให้เข้าถึงฐานข้อมูลเนื่องจากจะถูกจัดเก็บด้วย WP cache API

ตัวเลือกมักจะ "สด" ในฐานข้อมูลและจะคงอยู่ตลอดเวลานั่นคือแหล่ง "ยอมรับ" ของพวกเขา ที่กล่าวว่ามีการโหลดตัวเลือกลงในแคชวัตถุดังนั้นเมื่อคุณขอตัวเลือกมีโอกาส 99% ที่คำขอจะไม่ตีฐานข้อมูล

ชั่วครู่แตกต่างกันเล็กน้อย

WordPress ช่วยให้คุณสามารถแทนที่แคช api ด้วยดรอปอิน - ไฟล์ที่วางโดยตรงในwp-contentโฟลเดอร์ของคุณ หากคุณสร้างแคชของคุณเองหรือใช้ปลั๊กอินที่มีอยู่ คุณสามารถทำให้แคชวัตถุยังคงอยู่นานกว่าการโหลดหน้าเดียว เมื่อคุณทำเช่นนั้นชั่วคราวเปลี่ยนเล็กน้อย

ลองดูที่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.phpหรือwp-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_cachewp-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 จะพยายามใช้แคชวัตถุภายนอกที่คงอยู่หากข้อมูลสามารถเข้าไปในตารางตัวเลือกและรับขยะที่เก็บรวบรวมผ่านทางpsuedo-cron ของ WordPressเมื่อหมดอายุ

ข้อสงสัย / คำถามอื่น ๆ :

  1. มันโอเคที่จะโทรมาหลายสายget_optionหรือไม่? อาจ. พวกเขาเรียกใช้ค่าใช้จ่ายของฟังก์ชั่น แต่มันอาจจะไม่ตีฐานข้อมูล การโหลดฐานข้อมูลมักเกี่ยวข้องกับความสามารถในการปรับขนาดของเว็บแอ็พพลิเคชันได้ดีกว่าภาษาที่คุณเลือกจะสร้างหน้าขึ้นมา
  2. ฉันจะทราบได้อย่างไรว่าใช้ชั่วคราวกับ Cache API หากคุณคาดว่าข้อมูลจะคงอยู่ในช่วงเวลาที่กำหนดให้ใช้ transient API หากไม่สำคัญว่าข้อมูลยังคงอยู่ (เช่นใช้เวลาไม่นานในการคำนวณ / ดึงข้อมูล แต่ไม่ควรเกิดขึ้นมากกว่าหนึ่งครั้งต่อการโหลดหน้าเว็บ) ใช้แคช API
  3. ตัวเลือกทั้งหมดจะถูกแคชจริง ๆ ในทุก ๆ pageload หรือไม่? ไม่จำเป็น. หากคุณโทรadd_optionด้วยอาร์กิวเมนต์ตัวสุดท้ายตัวเลือกnoนั้นจะไม่ถูกโหลดอัตโนมัติ ที่กล่าวว่าเมื่อคุณดึงข้อมูลพวกเขาครั้งเดียวพวกเขาเข้าไปในแคชและการโทรที่ตามมาจะไม่กระทบกับฐานข้อมูล

nitpick 1: ไม่ได้โหลดตัวเลือกทั้งหมดเมื่อเริ่มต้นหน้า แต่จะมีเฉพาะตัวเลือกที่มีการทำเครื่องหมาย "autoload = ใช่" เมื่อสร้าง ค่าเริ่มต้นสำหรับพารามิเตอร์นั้นใน add_option คือ 'ใช่' และนักเขียนปลั๊กอินส่วนใหญ่ไม่สนใจที่จะเข้าใจความแตกต่างในการใช้ 'ไม่' เพื่อทำให้คำสั่งของคุณเป็นจริง
Mark Kaplun

แม้ตัวเลือกที่ไม่โหลดอัตโนมัติจะถูกแคชหลังจากถูกดึงออกมาหนึ่งครั้ง อาจไม่สามารถโหลดได้ในตอนแรก แต่จะเข้าสู่แคชวัตถุหลังจากนั้น แม้แต่ตัวเลือกที่ไม่มีอยู่ก็ถูกแคช! github.com/WordPress/WordPress/blob/master/wp-includes/ ......ฉันได้เพิ่มข้อความเกี่ยวกับตัวเลือก autoload อย่างไรก็ตาม
chrisguitarguy

นั่นคือ nitpick 2;)
Mark Kaplun

ขอบคุณสำหรับบทความที่ยอดเยี่ยมและสำหรับช่วงเวลาสรุปทั้งหมดนั้น
prosti

5

มีแคช 4 ประเภทที่ฉันรู้จัก

  1. Trivial - มันเปิดอยู่เสมอและจะมีผลก่อนที่จะมีการแคชอื่น ๆ เข้ามาเล่น จะเก็บรายการที่แคชไว้ในอาร์เรย์ php ซึ่งหมายความว่ามันจะใช้หน่วยความจำจากเซสชันการดำเนินการ php ของคุณและแคชจะถูกล้างหลังจากการดำเนินการ php สิ้นสุดลง เช่นแม้ไม่ใช้แคชอื่น ๆ ถ้าคุณเรียกใช้ get_option ('opt') สองครั้งในแถวคุณจะทำการสืบค้น DB ในครั้งแรกและครั้งที่สองที่ค่าจะถูกส่งคืนจากหน่วยความจำ

  2. ไฟล์ - ค่าที่เก็บไว้จะถูกเก็บไว้ในไฟล์บางแห่งภายใต้ไดเรกทอรีรากของคุณ ฉันเชื่อว่ามันพิสูจน์แล้วว่าไม่มีประสิทธิภาพในแง่ของประสิทธิภาพเว้นแต่คุณจะมีที่จัดเก็บไฟล์ที่แมปไฟล์ที่รวดเร็วมากหรือหน่วยความจำ

  3. APC (หรือการแคชที่ใช้ตัวเร่ง php อื่น ๆ ) - ค่าที่เก็บไว้จะถูกเก็บไว้ในหน่วยความจำของเครื่องโฮสต์และนอกการจัดสรรหน่วยความจำ php ของคุณ ข้อผิดพลาดที่ใหญ่ที่สุดที่อาจเกิดขึ้นคือไม่มีการกำหนดขอบเขตของข้อมูลและหากคุณเรียกใช้สองไซต์ที่มีศักยภาพแต่ละแห่งสามารถเข้าถึงข้อมูลที่แคชของอีกไซต์หนึ่งหรือเขียนทับมัน

  4. Memcache - เป็นเครือข่ายแคช คุณสามารถเรียกใช้บริการแคชได้ทุกที่บนเครือข่ายและมันอาจเก็บค่าในหน่วยความจำโฮสต์ คุณอาจไม่จำเป็นต้องใช้ memcache นอกจากว่าคุณจะมีการปรับสมดุลภาระในการทำงาน

BTW, การแคชวัตถุกำลังแคชมากกว่าตัวเลือกมันจะเก็บเกือบทุกอย่างที่ดึงมาจากฐานข้อมูลโดยใช้ WP API ระดับสูง


ฉันรู้ว่าคำตอบนั้นค่อนข้างเก่า แต่ฉันจะเพิ่มRedis ที่ยอดเยี่ยมด้วย
Cranio

@Cranio คุณพูดถูก แต่ ... redis นั้นเป็นตัวแปรของ memcache พร้อมที่เก็บข้อมูลและมันก็คือ DB (NoSQL) IMHO นี้จริง ๆ แล้วไม่ดีเหมือนว่าโหนดล้มเหลวหรือไม่สามารถปรับปรุงคุณอาจได้รับข้อมูลเก่า มันมีตัวเลือกให้ปิดฐานข้อมูลแบบพฤติกรรม แต่ฉันไม่แน่ใจว่าจะเปิดหรือปิดโดยค่าเริ่มต้น
Mark Kaplun

มันเป็นการทดแทนที่สมบูรณ์แบบสำหรับ Memcached (ดียิ่งขึ้น) คุณต้องการอะไรอีก การใช้งานที่พบบ่อยที่สุดที่ฉันเคยเห็นก็เหมือนกับการจัดเก็บคีย์ - ค่า RAM (ใช่นอกเหนือจากนั้นสามารถทำให้ข้อมูลถาวรได้การจัดกลุ่มกำลังดำเนินการอยู่และมีความสามารถในการจัดการคิว แต่ทุกคนเพิ่ม Redis ให้เป็นเลิศ ตัวเลือกแคชสำหรับ WP)
Cranio

ทุกคนสามารถกระโดดจากสะพานได้ด้วย) แต่ความซับซ้อนที่เพิ่มขึ้นนั้นไม่จำเป็นสำหรับการแคชโดยสิ้นเชิง
Mark Kaplun

นั่นไม่มีจุดหมายอย่างสมบูรณ์; คุณต้องการแคช RAM, Redis ทำการแคช RAM, ช่วงเวลา; และมันก็ทำอย่างมหัศจรรย์ ไม่มีความซับซ้อนเพิ่มอย่างแน่นอนถ้าคุณไม่ต้องการที่จะไป ดังนั้นฉันเลยไม่เข้าใจประเด็นของคุณ
Cranio

0

ตัวเลือกจะถูกเก็บไว้ในฐานข้อมูลเสมอในขณะที่ transients อาจถูกเก็บไว้ในหน่วยความจำที่ใช้ร่วมกันเฉพาะถ้า APC และปลั๊กอินที่ใช้การแคช APC ใน WP ถูกติดตั้ง Memcache ใช้หน่วยความจำเช่นกัน

ตัวเลือกจะถูกเก็บไว้ในหน่วยความจำและโหลดจากที่นั่นเมื่อเป็นไปได้ (ถ้าไม่ใช่จะทำการสืบค้น db)


0

เป็นคำถามที่ดีมาก

ฉันคิดว่าส่วนที่ว่า WordPress ใช้WP_Object_Cacheคลาสนั้นยังขาดหายไปดังนั้นฉันจะเพิ่มสิ่งนั้น

จากเอกสาร:

DEF: แคชวัตถุ WordPress ใช้เพื่อบันทึกการเดินทางไปยังฐานข้อมูล Object Cache เก็บข้อมูลแคชทั้งหมดไปยังหน่วยความจำและทำให้เนื้อหาแคชพร้อมใช้งานโดยใช้คีย์ซึ่งใช้เพื่อตั้งชื่อและเรียกเนื้อหาแคชในภายหลัง

นี่คือ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.