Làm thế nào để bộ nhớ đệm đối tượng hoạt động?


21

Tôi đang tìm kiếm một câu trả lời dứt khoát ở đây. Khi bộ nhớ đệm đối tượng được bật, các tùy chọn và tạm thời kết thúc ở đâu?

Theo mặc định, cả hai được lưu trữ trong cơ sở dữ liệu. Nhưng tôi đã nghe một số tài liệu tham khảo rằng memcache sẽ lưu trữ chúng ở nơi khác và APC sẽ làm một cái gì đó hoàn toàn khác. Trong trường hợp, chính xác , sẽ dữ liệu này được tiếp tục tồn tại cả hai trường hợp?


2
Bài viết @toscho đề cập hiện có sẵn trên archive.org: Khám phá API bộ nhớ cache của WordPress
tại đây vào

Câu trả lời:


34

Theo mặc định, WordPress thực hiện một dạng "Bộ nhớ đệm đối tượng" nhưng thời gian tồn tại của nó chỉ là một trang tải duy nhất.

Các tùy chọn thực sự là một ví dụ thực sự tốt về điều này. Kiểm tra câu trả lời này để biết thêm. Tóm tắt:

  1. Một trang bắt đầu
  2. Tất cả các tùy chọn được tải với một SELECT option_name, option_value from $wpdb->optionstuyên bố đơn giản
  3. Các yêu cầu tiếp theo cho các tùy chọn đó (ví dụ: một cuộc gọi get_optionkhông bao giờ nhấn vào cơ sở dữ liệu vì chúng được lưu trữ với API bộ đệm WP.

Các tùy chọn luôn "sống" trong cơ sở dữ liệu và luôn được duy trì ở đó - đó là nguồn "chính tắc" của chúng. Điều đó nói rằng, các tùy chọn được tải vào bộ đệm đối tượng để khi bạn yêu cầu một tùy chọn, có 99% khả năng yêu cầu đó sẽ không bao giờ đánh vào cơ sở dữ liệu.

Transents là một chút khác nhau.

WordPress cho phép bạn thay thế api bộ nhớ cache bằng trình đơn thả xuống - một tệp được đặt trực tiếp trong wp-contentthư mục của bạn . Nếu bạn tạo bộ đệm riêng của mình thả vào hoặc sử dụng một plugin hiện có , bạn có thể làm cho bộ đệm đối tượng tồn tại lâu hơn một lần tải trang. Khi bạn làm điều đó, tạm thời, thay đổi một chút.

Chúng ta hãy xem set_transientchức năng trong 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;
}

Hừm $_wp_using_ext_object_cache? Nếu đó là sự thật, WordPress sử dụng bộ đệm đối tượng thay vì cơ sở dữ liệu để lưu trữ quá độ. Vì vậy, làm thế nào mà được thiết lập thành đúng? Thời gian để khám phá cách WP thiết lập API bộ nhớ cache của riêng mình.

Bạn có thể theo dõi hầu hết mọi thứ wp-load.phphoặc wp-settings.php- cả hai đều quan trọng đối với quá trình bootstrap của WordPress. Trong bộ nhớ cache của chúng tôi, có một số dòng có liên quan wp-settings.php.

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

Hãy nhớ rằng thả trong điều từ trên? Chúng ta hãy xem xét wp_start_object_cachetrong 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' ) );
    }
}

Các dòng có liên quan của hàm (những dòng liên quan đến $_wp_using_ext_object_cacheđiều đó thay đổi cách lưu trữ quá độ).

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

nếu object-cache.phptồn tại trong thư mục nội dung của bạn, nó sẽ được bao gồm và WP giả định rằng bạn đang sử dụng bộ đệm ẩn bên ngoài, liên tục - nó được đặt $_wp_using_ext_object_cachethành đúng.

Nếu bạn đang sử dụng một bộ đệm tạm thời đối tượng bên ngoài sẽ sử dụng nó. Điều này đưa ra câu hỏi khi nào nên sử dụng tùy chọn so với tạm thời.

Đơn giản. Nếu bạn cần dữ liệu để tồn tại vô thời hạn, hãy sử dụng các tùy chọn. Họ nhận được "lưu trữ", nhưng nguồn chính của họ là cơ sở dữ liệu và họ sẽ không bao giờ biến mất trừ khi người dùng yêu cầu rõ ràng.

Đối với dữ liệu nên được lưu trữ trong một khoảng thời gian đã đặt, nhưng không cần phải vượt quá thời gian sử dụng trọn đời được chỉ định. Trong nội bộ, WP sẽ cố gắng sử dụng bộ đệm đối tượng liên tục, bên ngoài nếu có thể dữ liệu sẽ đi vào bảng tùy chọn và nhận rác được thu thập thông qua psuedo-cron của WordPress khi chúng hết hạn.

Một số mối quan tâm / câu hỏi khác:

  1. Có thể thực hiện một tấn các cuộc gọi đến get_option? Có lẽ. Họ phải chịu một cuộc gọi đến chức năng, nhưng có khả năng nó sẽ không trúng cơ sở dữ liệu. Tải cơ sở dữ liệu thường là mối quan tâm lớn hơn về khả năng mở rộng ứng dụng web so với công việc mà ngôn ngữ bạn chọn tạo ra một trang.
  2. Làm cách nào để biết cách sử dụng tạm thời so với API Cache? Nếu bạn muốn dữ liệu tồn tại trong một khoảng thời gian đã đặt, hãy sử dụng API tạm thời. Nếu không có vấn đề gì nếu dữ liệu vẫn tồn tại (ví dụ: sẽ không mất nhiều thời gian để tính toán / tìm nạp dữ liệu, nhưng điều đó không nên xảy ra nhiều hơn một lần cho mỗi lần tải trang) sử dụng API bộ đệm.
  3. Có phải tất cả các tùy chọn thực sự được lưu trữ trên mỗi trang tải? Không cần thiết. Nếu bạn gọi add_optionvới đối số cuối cùng, tùy chọn vì nochúng không được tự động tải. Điều đó nói rằng, một khi bạn tìm nạp chúng một lần, chúng sẽ vào bộ đệm và các cuộc gọi tiếp theo sẽ không vào cơ sở dữ liệu.

nitpick 1: Không phải tất cả các tùy chọn được tải khi bắt đầu trang, mà chỉ những tùy chọn được đánh dấu "autoload = yes" khi được tạo. Mặc định cho tham số đó trong add_option là 'có' và hầu hết người viết plugin không bận tâm để hiểu sự khác biệt trong việc sử dụng 'không' ở đó làm cho tuyên bố của bạn thực tế đúng.
Đánh dấu Kaplun

Ngay cả các tùy chọn không được tải tự động cũng được lưu trữ sau khi chúng được tìm nạp một lần. Chúng có thể không được tải ban đầu, nhưng chúng sẽ đi vào bộ đệm đối tượng sau đó. Ngay cả các tùy chọn không tồn tại cũng được lưu trữ! github.com/WordPress/WordPress/blob/master/wp-includes/ mẹo Tôi đã thêm một lưu ý về tùy chọn tự động tải, tuy nhiên.
chrisguitarguy

đó là nitpick 2;)
Mark Kaplun

Cảm ơn bạn cho bài viết tuyệt vời, và đã dành thời gian tóm tắt tất cả những điều đó.
prosti

5

Có 4 loại bộ đệm mà tôi biết

  1. Trivial - Nó luôn luôn bật và ảnh hưởng trước khi bất kỳ bộ nhớ đệm nào khác xuất hiện. Nó lưu trữ các mục được lưu trong bộ đệm php, điều đó có nghĩa là nó tiêu thụ bộ nhớ từ phiên thực thi php của bạn và bộ đệm được xóa sau khi kết thúc quá trình php. tức là ngay cả khi không sử dụng bất kỳ bộ đệm nào khác nếu bạn gọi get_option ('opt') hai lần liên tiếp, bạn sẽ thực hiện truy vấn DB lần đầu tiên và lần thứ hai giá trị sẽ được trả về từ bộ nhớ.

  2. Tệp - Các giá trị được lưu trong bộ nhớ cache được lưu trữ trong các tệp ở đâu đó trong thư mục gốc của bạn. Tôi tin rằng nó đã được chứng minh là không hiệu quả về mặt hiệu suất trừ khi bạn có một bộ lưu trữ tệp ánh xạ đĩa hoặc bộ nhớ rất nhanh.

  3. APC (hoặc bộ đệm ẩn dựa trên bộ tăng tốc php khác) - Các giá trị được lưu trong bộ nhớ cache được lưu trữ trong bộ nhớ của máy chủ và bên ngoài phân bổ bộ nhớ php của bạn. Cạm bẫy tiềm năng lớn nhất là không có phạm vi dữ liệu và nếu bạn chạy hai trang có khả năng thì mỗi trang có thể truy cập dữ liệu được lưu trong bộ nhớ cache của trang kia hoặc ghi đè lên dữ liệu đó.

  4. Memcache - nó là một bộ đệm dựa trên mạng. Bạn có thể chạy dịch vụ lưu trữ bất cứ nơi nào trên mạng và nó có thể lưu các giá trị trong bộ nhớ máy chủ của nó. Bạn có thể không cần memcache trừ khi bạn có cân bằng tải trong hành động.

BTW, bộ nhớ đệm đối tượng là bộ nhớ đệm nhiều hơn các tùy chọn, nó sẽ lưu trữ hầu hết mọi thứ được lấy từ DB bằng API WP cấp cao.


Tôi biết câu trả lời khá cũ, nhưng tôi cũng sẽ thêm Redis xuất sắc .
Cranio

@Cranio, bạn đúng nhưng ... redis về cơ bản là một biến thể của memcache với bộ lưu trữ và do đó nó là một DB (NoQuery). IMHO này thực sự xấu vì nếu nút bị lỗi hoặc không thể cập nhật, bạn có thể nhận được thông tin cũ từ nó. Nó có một tùy chọn để tắt hành vi như DB nhưng tôi không chắc nó được bật hay tắt theo mặc định.
Đánh dấu Kaplun

Nó là một sự thay thế hoàn hảo cho Memcached (thậm chí tốt hơn), bạn cần gì nữa? Cho đến nay, cách sử dụng phổ biến nhất mà tôi thấy chỉ là lưu trữ giá trị khóa RAM (vâng, ngoài điều đó, dữ liệu có thể được thực hiện liên tục, phân cụm đang trên đường và có khả năng quản lý hàng đợi, nhưng mọi người đều thêm Redis là một công cụ tuyệt vời tùy chọn bộ nhớ đệm cho WP)
Cranio

mọi người cũng có thể nhảy cầu;) nhưng sự phức tạp thêm vào là hoàn toàn không cần thiết cho bộ nhớ đệm
Mark Kaplun

Điều đó hoàn toàn vô nghĩa; bạn muốn bộ nhớ cache RAM, Redis làm bộ nhớ cache RAM, thời gian; và nó làm điều đó tuyệt vời. Hoàn toàn không có sự phức tạp thêm vào nếu bạn không muốn đi cho nó. Vì vậy, thưa ngài, tôi thực sự không hiểu quan điểm của bạn.
Cranio

0

Các tùy chọn luôn được lưu trữ trong cơ sở dữ liệu, trong khi các quá độ chỉ có thể được lưu trữ trong bộ nhớ dùng chung nếu APC và một plugin thực hiện bộ nhớ đệm APC trong WP được cài đặt. Memcache cũng sử dụng bộ nhớ.

Các tùy chọn cũng được lưu trữ trong bộ nhớ và được tải từ đó khi có thể (nếu không, một truy vấn db được thực hiện).


0

Câu hỏi tuyệt vời.

Tôi nghĩ rằng phần WordPress sử dụng WP_Object_Cachelớp vẫn còn thiếu, vì vậy tôi sẽ thêm phần đó.

Từ các tài liệu:

DEF: Bộ đệm đối tượng WordPress được sử dụng để lưu trong các chuyến đi đến cơ sở dữ liệu. Object Cache lưu trữ tất cả dữ liệu bộ nhớ cache vào bộ nhớ và làm cho nội dung bộ đệm có sẵn bằng cách sử dụng một khóa, được sử dụng để đặt tên và sau đó truy xuất nội dung bộ đệm.

Đây là WP_Object_Cachecấu trúc.

nhập mô tả hình ảnh ở đây

Lưu ý + là công khai, - riêng tư, # được bảo vệ.

Bạn sử dụng stats()phương pháp để hiển thị số liệu thống kê chung về đối tượng bộ đệm chung và những gì có trong đó. Đây là đầu ra:

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 )

Đây là những gì tôi đã nhận được trước khi bắt đầu một mẫu như single.php.

Lưu ý biến chúng ta quan tâm là : global $wp_object_cache.

Các thành viên riêng $cachegiữ dữ liệu bộ nhớ đệm thực tế.

Trong lập trình, cấu trúc bộ đệm có ở khắp mọi nơi. Trong một hình thức đơn giản, chúng có thể được công nhận là một cặp giá trị chính. Xô, cấu trúc NoDB, chỉ mục cơ sở dữ liệu. Mục tiêu cuối cùng của WordPress Object Cache là không có cấu trúc đơn giản nhất có thể, nhưng vẫn có thể nhận ra các cặp giá trị chính.

Vì tôi đã ở trong single.phpkhi tôi in bộ đệm:

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

Tôi nhận được một bài đăng duy nhất lưu trữ.

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

Đối tượng sẽ là giá trị và khóa bộ đệm sẽ là

get_page_by_path:2516f01e446b6c125493ec7824b63868:0.34169600 1481802075

Ở đây bạn có thể kiểm tra $cache_keycấu trúc:

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:   }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.