Introduce wp_cache_switch_to_blog() and WP_Object_Cache::switch_to_blog() as a lighter/faster way to switch the cache to a new blog id.

Add the blog id to the cache keys for multisite installs.

Use wp_cache_switch_to_blog() instead of wp_cache_init() in switch_to_blog().

Use wp_cache_switch_to_blog() instead of wp_cache_reset() in wp_start_object_cache().

Deprecate wp_cache_reset().

This avoids the many queries needed to re-prime the cache after switch_to_blog() on multisite installs using the default cache backend.

fixes #21434



git-svn-id: https://develop.svn.wordpress.org/trunk@21403 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Ryan Boren 2012-08-02 18:31:14 +00:00
parent ecd9fe3d78
commit 691425a3ff
3 changed files with 115 additions and 38 deletions

View File

@ -179,6 +179,19 @@ function wp_cache_set($key, $data, $group = '', $expire = 0) {
return $wp_object_cache->set($key, $data, $group, $expire); return $wp_object_cache->set($key, $data, $group, $expire);
} }
/**
* Switch the interal blog id.
*
* This changes the blog id used to create keys in blog specific groups.
*
* @param int $blog_id Blog ID
*/
function wp_cache_switch_to_blog( $blog_id ) {
global $wp_object_cache;
return $wp_object_cache->switch_to_blog( $blog_id );
}
/** /**
* Adds a group or set of groups to the list of global groups. * Adds a group or set of groups to the list of global groups.
* *
@ -189,7 +202,7 @@ function wp_cache_set($key, $data, $group = '', $expire = 0) {
function wp_cache_add_global_groups( $groups ) { function wp_cache_add_global_groups( $groups ) {
global $wp_object_cache; global $wp_object_cache;
return $wp_object_cache->add_global_groups($groups); return $wp_object_cache->add_global_groups( $groups );
} }
/** /**
@ -209,8 +222,11 @@ function wp_cache_add_non_persistent_groups( $groups ) {
* this function instructs the backend to reset those keys and perform any cleanup since blog or site IDs have changed since cache init. * this function instructs the backend to reset those keys and perform any cleanup since blog or site IDs have changed since cache init.
* *
* @since 2.6.0 * @since 2.6.0
* @deprecated 3.5.0
*/ */
function wp_cache_reset() { function wp_cache_reset() {
_deprecated_function( __FUNCTION__, '3.5', 'wp_cache_switch_to_blog()' );
global $wp_object_cache; global $wp_object_cache;
return $wp_object_cache->reset(); return $wp_object_cache->reset();
@ -270,6 +286,15 @@ class WP_Object_Cache {
*/ */
var $global_groups = array(); var $global_groups = array();
/**
* The blog prefix to prepend to keys in non-global groups.
*
* @var int
* @access private
* @since 3.5.0
*/
var $blog_prefix;
/** /**
* Adds data to the cache if it doesn't already exist. * Adds data to the cache if it doesn't already exist.
* *
@ -292,7 +317,11 @@ class WP_Object_Cache {
if ( empty( $group ) ) if ( empty( $group ) )
$group = 'default'; $group = 'default';
if ( $this->_exists($key, $group) ) $id = $key;
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
$id = $this->blog_prefix . $key;
if ( $this->_exists( $id, $group ) )
return false; return false;
return $this->set($key, $data, $group, $expire); return $this->set($key, $data, $group, $expire);
@ -308,8 +337,8 @@ class WP_Object_Cache {
function add_global_groups( $groups ) { function add_global_groups( $groups ) {
$groups = (array) $groups; $groups = (array) $groups;
$this->global_groups = array_merge($this->global_groups, $groups); $groups = array_fill_keys( $groups, true );
$this->global_groups = array_unique($this->global_groups); $this->global_groups = array_merge( $this->global_groups, $groups );
} }
/** /**
@ -325,7 +354,10 @@ class WP_Object_Cache {
function decr( $key, $offset = 1, $group = 'default' ) { function decr( $key, $offset = 1, $group = 'default' ) {
if ( empty( $group ) ) if ( empty( $group ) )
$group = 'default'; $group = 'default';
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
$key = $this->blog_prefix . $key;
if ( ! $this->_exists( $key, $group ) ) if ( ! $this->_exists( $key, $group ) )
return false; return false;
@ -361,6 +393,9 @@ class WP_Object_Cache {
if ( empty( $group ) ) if ( empty( $group ) )
$group = 'default'; $group = 'default';
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
$key = $this->blog_prefix . $key;
if ( ! $force && ! $this->_exists( $key, $group ) ) if ( ! $force && ! $this->_exists( $key, $group ) )
return false; return false;
@ -402,6 +437,9 @@ class WP_Object_Cache {
if ( empty( $group ) ) if ( empty( $group ) )
$group = 'default'; $group = 'default';
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
$key = $this->blog_prefix . $key;
if ( $this->_exists( $key, $group ) ) { if ( $this->_exists( $key, $group ) ) {
$found = true; $found = true;
$this->cache_hits += 1; $this->cache_hits += 1;
@ -430,6 +468,9 @@ class WP_Object_Cache {
if ( empty( $group ) ) if ( empty( $group ) )
$group = 'default'; $group = 'default';
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
$key = $this->blog_prefix . $key;
if ( ! $this->_exists( $key, $group ) ) if ( ! $this->_exists( $key, $group ) )
return false; return false;
@ -458,26 +499,33 @@ class WP_Object_Cache {
* @param int $expire When to expire the cache contents * @param int $expire When to expire the cache contents
* @return bool False if not exists, true if contents were replaced * @return bool False if not exists, true if contents were replaced
*/ */
function replace($key, $data, $group = 'default', $expire = '') { function replace( $key, $data, $group = 'default', $expire = '' ) {
if ( empty( $group ) ) if ( empty( $group ) )
$group = 'default'; $group = 'default';
if ( ! $this->_exists( $key, $group ) ) $id = $key;
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
$id = $this->blog_prefix . $key;
if ( ! $this->_exists( $id, $group ) )
return false; return false;
return $this->set($key, $data, $group, $expire); return $this->set( $key, $data, $group, $expire );
} }
/** /**
* Reset keys * Reset keys
* *
* @since 3.0.0 * @since 3.0.0
* @deprecated 3.5.0
*/ */
function reset() { function reset() {
_deprecated_function( __FUNCTION__, '3.5', 'switch_to_blog()' );
// Clear out non-global caches since the blog ID has changed. // Clear out non-global caches since the blog ID has changed.
foreach ( array_keys($this->cache) as $group ) { foreach ( array_keys( $this->cache ) as $group ) {
if ( !in_array($group, $this->global_groups) ) if ( ! isset( $this->global_groups[ $group ] ) )
unset($this->cache[$group]); unset( $this->cache[ $group ] );
} }
} }
@ -505,7 +553,10 @@ class WP_Object_Cache {
if ( empty( $group ) ) if ( empty( $group ) )
$group = 'default'; $group = 'default';
if ( is_object($data) ) if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
$key = $this->blog_prefix . $key;
if ( is_object( $data ) )
$data = clone $data; $data = clone $data;
$this->cache[$group][$key] = $data; $this->cache[$group][$key] = $data;
@ -532,6 +583,18 @@ class WP_Object_Cache {
echo '</ul>'; echo '</ul>';
} }
/**
* Switch the interal blog id.
*
* This changes the blog id used to create keys in blog specific groups.
*
* @param int $blog_id Blog ID
*/
function switch_to_blog( $blog_id ) {
$blog_id = (int) $blog_id;
$this->blog_prefix = $this->multisite ? $blog_id . ':' : '';
}
/** /**
* Utility function to determine whether a key exists in the cache. * Utility function to determine whether a key exists in the cache.
* *
@ -550,11 +613,17 @@ class WP_Object_Cache {
* @return null|WP_Object_Cache If cache is disabled, returns null. * @return null|WP_Object_Cache If cache is disabled, returns null.
*/ */
function __construct() { function __construct() {
global $blog_id;
$this->multisite = is_multisite();
$this->blog_prefix = $this->multisite ? $blog_id . ':' : '';
/** /**
* @todo This should be moved to the PHP4 style constructor, PHP5 * @todo This should be moved to the PHP4 style constructor, PHP5
* already calls __destruct() * already calls __destruct()
*/ */
register_shutdown_function(array(&$this, "__destruct")); register_shutdown_function( array( &$this, '__destruct' ) );
} }
/** /**

View File

@ -381,7 +381,7 @@ function wp_set_wpdb_vars() {
* @since 3.0.0 * @since 3.0.0
*/ */
function wp_start_object_cache() { function wp_start_object_cache() {
global $_wp_using_ext_object_cache; global $_wp_using_ext_object_cache, $blog_id;
$first_init = false; $first_init = false;
if ( ! function_exists( 'wp_cache_init' ) ) { if ( ! function_exists( 'wp_cache_init' ) ) {
@ -403,8 +403,8 @@ function wp_start_object_cache() {
// If cache supports reset, reset instead of init if already initialized. // 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 // Reset signals to the cache that global IDs have changed and it may need to update keys
// and cleanup caches. // and cleanup caches.
if ( !$first_init && function_exists('wp_cache_reset') ) if ( ! $first_init && function_exists( 'wp_cache_switch_to_blog' ) )
wp_cache_reset(); wp_cache_switch_to_blog( $blog_id );
else else
wp_cache_init(); wp_cache_init();

View File

@ -487,18 +487,22 @@ function switch_to_blog( $new_blog, $validate = false ) {
$current_user->for_blog( $blog_id ); $current_user->for_blog( $blog_id );
} }
if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) ) if ( function_exists( 'wp_cache_switch_to_blog' ) ) {
$global_groups = $wp_object_cache->global_groups; wp_cache_switch_to_blog( $blog_id );
else } else {
$global_groups = false; if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) )
$global_groups = $wp_object_cache->global_groups;
wp_cache_init();
if ( function_exists('wp_cache_add_global_groups') ) {
if ( is_array( $global_groups ) )
wp_cache_add_global_groups( $global_groups );
else else
wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts' ) ); $global_groups = false;
wp_cache_add_non_persistent_groups(array( 'comment', 'counts', 'plugins' ));
wp_cache_init();
if ( function_exists('wp_cache_add_global_groups') ) {
if ( is_array( $global_groups ) )
wp_cache_add_global_groups( $global_groups );
else
wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts' ) );
wp_cache_add_non_persistent_groups(array( 'comment', 'counts', 'plugins' ));
}
} }
do_action('switch_blog', $blog_id, $prev_blog_id); do_action('switch_blog', $blog_id, $prev_blog_id);
@ -551,18 +555,22 @@ function restore_current_blog() {
$current_user->for_blog( $blog_id ); $current_user->for_blog( $blog_id );
} }
if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) ) if ( function_exists( 'wp_cache_switch_to_blog' ) ) {
$global_groups = $wp_object_cache->global_groups; wp_cache_switch_to_blog( $blog_id );
else } else {
$global_groups = false; if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) )
$global_groups = $wp_object_cache->global_groups;
wp_cache_init();
if ( function_exists('wp_cache_add_global_groups') ) {
if ( is_array( $global_groups ) )
wp_cache_add_global_groups( $global_groups );
else else
wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts' ) ); $global_groups = false;
wp_cache_add_non_persistent_groups(array( 'comment', 'counts', 'plugins' ));
wp_cache_init();
if ( function_exists('wp_cache_add_global_groups') ) {
if ( is_array( $global_groups ) )
wp_cache_add_global_groups( $global_groups );
else
wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts' ) );
wp_cache_add_non_persistent_groups(array( 'comment', 'counts', 'plugins' ));
}
} }
do_action('switch_blog', $blog_id, $prev_blog_id); do_action('switch_blog', $blog_id, $prev_blog_id);