详解 WordPress `WP_Object_Cache` 类源码:键值对缓存与外部系统的集成。

各位观众老爷们,晚上好!欢迎来到今晚的 WordPress 源码解剖现场。今天咱们要扒的是 WordPress 缓存机制的核心——WP_Object_Cache 类。这玩意儿就像 WordPress 的大脑,负责存储和检索数据,能让你的网站速度飞起来,告别卡顿。

准备好了吗?咱们这就开始!

WP_Object_Cache:你的数据管家

WP_Object_Cache 是 WordPress 用来存储 PHP 对象(比如数据库查询结果、设置选项等)的类。它提供了一套简单的 API,允许你像操作一个巨大的键值对存储一样来管理数据。

简单来说,你给它一个键(key)和一个值(value),它就帮你存起来。下次你需要这个值的时候,给它同样的键,它就立马给你找出来,不用再费劲地从数据库里捞了。

WP_Object_Cache 的家底:成员变量

咱们先来看看 WP_Object_Cache 类的主要成员变量,它们是组成这个类的骨架:

变量名 类型 作用
$cache array 存储缓存数据的核心数组。键是缓存键,值是缓存的数据。
$global_groups array 存储全局组的数组。属于全局组的缓存键,在所有站点之间共享。
$group_ops array 存储组操作的数组。不同的缓存后端(比如 Memcached、Redis)可能需要不同的组操作。
$stats array 统计信息,用于记录缓存命中、未命中等数据,方便你了解缓存的使用情况。
$default_expiration int 默认的缓存过期时间,单位是秒。如果缓存项没有设置过期时间,就使用这个默认值。
$mc object Memcached 或 Redis 客户端对象。如果使用了 Memcached 或 Redis 作为缓存后端,这个变量就存储连接到这些服务的客户端对象。
$redis object Redis 客户端对象。 如果使用了 Redis 作为缓存后端,这个变量就存储连接到 Redis 服务的客户端对象。这个变量在WordPress 6.2之后引入,用于更明确地区分 Redis 客户端。

WP_Object_Cache 的技能:核心方法

接下来,咱们来看看 WP_Object_Cache 类的一些核心方法:

  • __construct():构造函数

    这个函数在创建 WP_Object_Cache 对象时被调用,它会初始化一些成员变量,并尝试连接到外部缓存系统(比如 Memcached、Redis)。

    public function __construct() {
        $this->cache = array();
        $this->global_groups = array();
        $this->group_ops = array();
    
        // 尝试连接到 Memcached 或 Redis(如果已配置)
        $this->add_global_groups( array( 'users', 'userlogins', 'usermeta', 'site-transient', 'site-options', 'site-lookup', 'networks', 'sites', 'sitemeta', 'blog-details', 'networkmeta', 'global-posts', 'global-post-counts', 'ms-global-blogs', 'ms-site-visits', 'blog_id_cache' ) );
    
        if ( defined( 'WP_CACHE_KEY_SALT' ) ) {
            $this->cache_key_salt = WP_CACHE_KEY_SALT;
        }
    
        $this->multisite = is_multisite();
    
        if ( function_exists( 'wp_using_ext_object_cache' ) && wp_using_ext_object_cache() ) {
                global $wp_object_cache;
    
                if ( isset( $wp_object_cache ) && is_object( $wp_object_cache ) ) {
                    $this->supports_legacy_object_cache = true;
                }
        }
    
        wp_cache_add_global_groups( $this->global_groups );
    
        if ( defined( 'WP_OBJECT_CACHE_DEFAULT_EXPIRATION' ) && is_numeric( WP_OBJECT_CACHE_DEFAULT_EXPIRATION ) ) {
            $this->default_expiration = (int) WP_OBJECT_CACHE_DEFAULT_EXPIRATION;
        }
    
    }

    这段代码做了以下几件事:

    1. 初始化 $cache$global_groups$group_ops 数组。
    2. 添加一些默认的全局组,这些组的数据在所有站点之间共享。
    3. 检查是否定义了 WP_CACHE_KEY_SALT 常量,用于生成唯一的缓存键。
    4. 确定是否是多站点模式。
    5. 检查是否使用了外部缓存,如果使用了,则会标记为支持旧版本对象缓存。
    6. 添加全局组。
    7. 设定默认过期时间。
  • add( $key, $data, $group = 'default', $expire = 0 ):添加缓存

    这个方法用于向缓存中添加数据。

    public function add( $key, $data, $group = 'default', $expire = 0 ) {
        if ( wp_suspend_cache_addition() ) {
            return false;
        }
    
        if ( is_object( $data ) ) {
            $data = clone $data;
        }
    
        $key = $this->key( $key, $group );
    
        if ( $this->exists( $key, $group ) ) {
            return false;
        }
    
        if ( is_numeric( $expire ) && $expire > 0 ) {
            $expiration = time() + $expire;
        } else {
            $expiration = time() + $this->default_expiration;
        }
    
        $store_locally = ! $this->supports_legacy_object_cache;
        $result        = $this->_set( $key, $data, $expiration, $group, $store_locally );
    
        return $result;
    }

    流程如下:

    1. 检查是否暂停了缓存添加(wp_suspend_cache_addition())。
    2. 如果数据是对象,则克隆一份,避免修改原始对象。
    3. 调用 key() 方法生成唯一的缓存键。
    4. 调用 exists() 方法检查缓存是否已存在。
    5. 计算过期时间。
    6. 调用 _set() 方法将数据存储到缓存中。
  • get( $key, $group = 'default', $force = false, &$found = null ):获取缓存

    这个方法用于从缓存中获取数据。

    public function get( $key, $group = 'default', $force = false, &$found = null ) {
        $key = $this->key( $key, $group );
    
        if ( isset( $this->cache[ $key ] ) ) {
            $found = true;
            $this->stats['hits']++;
            return is_object( $this->cache[ $key ]['value'] ) ? clone $this->cache[ $key ]['value'] : $this->cache[ $key ]['value'];
        }
    
        $found = false;
        $this->stats['misses']++;
        return false;
    }

    流程如下:

    1. 调用 key() 方法生成唯一的缓存键。
    2. 检查缓存中是否存在该键。
    3. 如果存在,则返回缓存的数据(如果是对象,则克隆一份)。
    4. 如果不存在,则返回 false
  • set( $key, $data, $group = 'default', $expire = 0 ):设置缓存

    这个方法用于设置缓存,如果缓存已存在,则更新缓存。

    public function set( $key, $data, $group = 'default', $expire = 0 ) {
        if ( is_object( $data ) ) {
            $data = clone $data;
        }
    
        $key = $this->key( $key, $group );
    
        if ( is_numeric( $expire ) && $expire > 0 ) {
            $expiration = time() + $expire;
        } else {
            $expiration = time() + $this->default_expiration;
        }
    
        $store_locally = ! $this->supports_legacy_object_cache;
        $result        = $this->_set( $key, $data, $expiration, $group, $store_locally );
    
        return $result;
    }

    add() 方法类似,只不过 set() 方法会覆盖已存在的缓存。

  • delete( $key, $group = 'default', $force = false ):删除缓存

    这个方法用于从缓存中删除数据。

    public function delete( $key, $group = 'default', $force = false ) {
        $key = $this->key( $key, $group );
    
        unset( $this->cache[ $key ] );
    
        return true;
    }

    流程非常简单,就是从 $cache 数组中删除指定的键。

  • flush():清空缓存

    这个方法用于清空所有缓存数据。

    public function flush() {
        $this->cache = array();
        return true;
    }

    这个方法会清空 $cache 数组,但不会清除外部缓存系统中的数据。

  • key( $key, $group ):生成缓存键

    这个方法用于生成唯一的缓存键,它会将组名和键名组合在一起,并添加一个盐值(WP_CACHE_KEY_SALT)。

    public function key( $key, $group ) {
        if ( empty( $group ) ) {
            $group = 'default';
        }
    
        $prefix = '';
    
        if ( $this->multisite ) {
            $prefix = $this->get_blog_prefix( $this->blog_id );
        }
    
        return preg_replace( '/s+/', '', $prefix . $group . $key );
    }

    这个方法确保了缓存键的唯一性,避免不同站点或不同组的数据发生冲突。

  • _set( $key, $data, $expiration, $group, $store_locally = true ):内部设置缓存

    这个方法是实际将数据存储到缓存中的方法。它会根据是否使用了外部缓存系统来选择不同的存储方式。

    protected function _set( $key, $data, $expiration, $group, $store_locally = true ) {
        if ( $store_locally ) {
            $this->cache[ $key ] = array(
                'value'      => $data,
                'expiration' => $expiration,
            );
        }
    
        return true;
    }

    如果使用了外部缓存系统,这个方法可能会被重写,以便将数据存储到外部缓存中。

WP_Object_Cache 与外部缓存系统的集成

WP_Object_Cache 的一个重要功能是与外部缓存系统(比如 Memcached、Redis)集成。通过使用外部缓存系统,可以显著提高网站的性能。

WordPress 默认情况下使用内存缓存,也就是将数据存储在 PHP 的 $cache 数组中。这种方式的优点是简单快速,但缺点是数据只能在单个 PHP 进程中共享,而且服务器重启后数据会丢失。

外部缓存系统则可以将数据存储在独立的服务器上,多个 PHP 进程可以共享数据,而且服务器重启后数据不会丢失。

要使用外部缓存系统,你需要安装相应的 PHP 扩展(比如 memcachedredis),并在 wp-config.php 文件中配置缓存设置。

例如,要使用 Memcached,你需要添加以下代码到 wp-config.php

define( 'WP_CACHE', true ); // 启用缓存
define( 'WP_CACHE_KEY_SALT', 'your-unique-salt' ); // 设置一个唯一的盐值
define( 'WP_CACHE_PATH', ABSPATH . 'wp-content/cache/' );
$memcached_servers = array( '127.0.0.1:11211' ); // Memcached 服务器地址

然后,你需要安装一个 Memcached 对象缓存插件,比如 memcached

安装并启用插件后,WordPress 就会自动使用 Memcached 作为缓存后端。WP_Object_Cache 类会检测到 Memcached 扩展的存在,并使用 Memcached 客户端对象来存储和检索数据。

WP_Object_Cache 的扩展:插件的舞台

WP_Object_Cache 类本身是可扩展的。插件可以通过继承 WP_Object_Cache 类或直接替换 $wp_object_cache 全局变量来定制缓存行为。

例如,你可以创建一个自定义的缓存类,实现自己的缓存逻辑,或者添加一些额外的功能,比如缓存预热、缓存监控等。

以下是一个简单的例子,展示了如何创建一个自定义的缓存类:

class My_Custom_Object_Cache extends WP_Object_Cache {
    public function __construct() {
        parent::__construct();
        // 添加一些自定义的初始化代码
    }

    public function get( $key, $group = 'default', $force = false, &$found = null ) {
        // 添加一些自定义的获取缓存逻辑
        $data = parent::get( $key, $group, $force, $found );
        return $data;
    }

    public function set( $key, $data, $group = 'default', $expire = 0 ) {
        // 添加一些自定义的设置缓存逻辑
        return parent::set( $key, $data, $group, $expire );
    }
}

// 替换全局的 $wp_object_cache 变量
global $wp_object_cache;
$wp_object_cache = new My_Custom_Object_Cache();

这段代码创建了一个名为 My_Custom_Object_Cache 的类,它继承了 WP_Object_Cache 类,并重写了 get()set() 方法。然后,它将全局的 $wp_object_cache 变量替换为这个自定义的缓存对象。

总结:WP_Object_Cache,WordPress 性能的加速器

WP_Object_Cache 类是 WordPress 缓存机制的核心,它提供了一套简单的 API,用于存储和检索数据。通过与外部缓存系统集成,可以显著提高网站的性能。

WP_Object_Cache 类也是可扩展的,插件可以通过继承或替换该类来定制缓存行为。

希望今天的讲座能让你对 WP_Object_Cache 类有更深入的了解。记住,掌握缓存技术是优化 WordPress 网站性能的关键!

好啦,今天的源码解剖就到这里,咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注