WordPress开启Memcached缓存加速

Memcached缓存作用

Memcached是一种高性能的分布式内存对象缓存系统,常用于加速动态Web应用程序。它的作用是将应用程序常用的数据缓存在内存中,避免重复的计算和数据库读写,从而提高网站的响应速度和性能。具体来说,Memcached缓存的作用包括:

  • 减少数据库负载:将频繁读写的数据存储在内存中,减少对数据库的访问,降低数据库负载,提高性能和稳定性。
  • 提高网站响应速度:由于Memcached是基于内存的缓存,存取数据的速度非常快,因此可以显著提高响应速度,减少用户等待时间。
  • 提高应用程序性能:通过使用Memcached缓存,应用程序可以减少计算量和I/O操作,降低服务器负载,提高稳定性。
  • 分布式缓存:Memcached可以部署在多台服务器上,构建分布式缓存系统,提高容量和可靠性,避免单点故障。

Memcached缓存可以大大提高Web应用程序的性能和稳定性,对于高并发访问的Web应用程序尤为重要。

教程

  • 进入软件管理,选择你正在使用的PHP版本,安装memcached扩展,也可以顺便安装opcache。
  •  
  • 20250611220036279-5297_fb6f650292a04201248aadeea802e880

    在 Session 配置中,将存储模式选择为 memcached。

20250611220148413-4657_1690dc1e04e49afc5696341bb5c1d79fWordPress设置

  1. 新建一个 object-cache.php 文件放到网站目录 /wp-content 下。
  2. 把代码复制到object-cache.php 文件里:
    <?php
    if(
    	// (isset($_POST['action']) && $_POST['action'] == 'query-attachments') ||
    	(isset($_GET['debug']) && $_GET['debug'] == 'sql')
    ){
    	return;
    }
    
    if(!defined('WP_CACHE_KEY_SALT'))
    	define('WP_CACHE_KEY_SALT', '');
    
    if(class_exists('Memcached')){
    	function wp_cache_add($key, $data, $group='', $expire=0){
    		global $wp_object_cache;
    		return $wp_object_cache->add($key, $data, $group, (int) $expire);
    	}
    
    	function wp_cache_cas($cas_token, $key, $data, $group='', $expire=0){
    		global $wp_object_cache;
    		return $wp_object_cache->cas($cas_token, $key, $data, $group, (int) $expire);
    	}
    
    	function wp_cache_close(){
    		global $wp_object_cache;
    		return $wp_object_cache->close();
    	}
    
    	function wp_cache_decr($key, $offset=1, $group=''){
    		global $wp_object_cache;
    		return $wp_object_cache->decr($key, $offset, $group);
    	}
    
    	function wp_cache_delete($key, $group=''){
    		global $wp_object_cache;
    		return $wp_object_cache->delete($key, $group);
    	}
    
    	function wp_cache_flush(){
    		global $wp_object_cache;
    		return $wp_object_cache->flush();
    	}
    
    	function wp_cache_get($key, $group='', $force=false, &$found=null){
    		global $wp_object_cache;
    		return $wp_object_cache->get($key, $group, $force, $found);
    	}
    	
    	function wp_cache_get_multiple($keys, $group='', $force=false){
    		global $wp_object_cache;
    		return $wp_object_cache->get_multiple($keys, $group, $force);
    	}
    
    	function wp_cache_get_with_cas($key, $group='', &$cas_token=null){
    		global $wp_object_cache;
    		return $wp_object_cache->get_with_cas($key, $group, $cas_token);
    	}
    
    	function wp_cache_incr($key, $offset=1, $group=''){
    		global $wp_object_cache;
    		return $wp_object_cache->incr($key, $offset, $group);
    	}
    
    	if(!isset($_GET['debug']) || $_GET['debug'] != 'sql'){
    		function wp_cache_init(){
    			$GLOBALS['wp_object_cache']	= new WP_Object_Cache();
    		}
    	}
    
    	function wp_cache_replace($key, $data, $group='', $expire=0){
    		global $wp_object_cache;
    		return $wp_object_cache->replace($key, $data, $group, (int) $expire);
    	}
    
    	// function wp_cache_set($key, $data, $group='', $expire=0){
    	// 	global $wp_object_cache;
    
    	// 	if(defined('WP_INSTALLING') == false){
    	// 		return $wp_object_cache->set($key, $data, $group, $expire);
    	// 	} else{
    	// 		return $wp_object_cache->delete($key, $group);
    	// 	}
    	// }
    
    	function wp_cache_set($key, $data, $group='', $expire=0){
    		global $wp_object_cache;
    		return $wp_object_cache->set($key, $data, $group, (int) $expire);
    	}
    
    	function wp_cache_switch_to_blog($blog_id){
    		global $wp_object_cache;
    		return $wp_object_cache->switch_to_blog($blog_id);
    	}
    
    	function wp_cache_add_global_groups($groups){
    		global $wp_object_cache;
    		$wp_object_cache->add_global_groups($groups);
    	}
    
    	function wp_cache_add_non_persistent_groups($groups){
    		global $wp_object_cache;
    		$wp_object_cache->add_non_persistent_groups($groups);
    	}
    
    	function wp_cache_get_stats(){
    		global $wp_object_cache;
    		return $wp_object_cache->get_stats();
    	}
    
    	class WP_Object_Cache{
    		private $cache 	= [];
    		private $mc		= null;
    
    		public $cache_hits		= 0;
    		public $cache_misses	= 0;
    
    		private $blog_prefix;
    		private $global_prefix;
    
    		protected $global_groups	= [];
    		protected $non_persistent_groups	= [];
    
    		public function add($id, $data, $group='default', $expire=0){
    			if(wp_suspend_cache_addition()){
    				return false;
    			}
    
    			$key=$this->build_key($id, $group);
    
    			if($this->is_non_persistent_group($group)){
    				if($this->internal_cache_exists($key)){
    					return false;
    				}else{
    					$this->add_to_internal_cache($key, $data);
    					return true;
    				}
    			}else{
    				$result	= $this->mc->add($key, $data, $expire);
    
    				if($this->mc->getResultCode() === Memcached::RES_SUCCESS){
    					$this->add_to_internal_cache($key, $data);
    				} else{
    					$this->delete_from_internal_cache($key);
    				}
    
    				return $result;
    			}
    		}
    
    		public function replace($id, $data, $group='default', $expire=0){
    			$key	= $this->build_key($id, $group);
    
    			if($this->is_non_persistent_group($group)){
    				if(!$this->internal_cache_exists($key)){
    					return false;
    				}else{
    					$this->add_to_internal_cache($key, $data);
    					return true;
    				}
    			}else{
    				$result=$this->mc->replace($key, $data, $expire);
    
    				if($this->mc->getResultCode() === Memcached::RES_SUCCESS){
    					$this->add_to_internal_cache($key, $data);
    				} else{
    					$this->delete_from_internal_cache($key);
    				}
    				
    				return $result;
    			}
    		}
    
    		public function set($id, $data, $group='default', $expire=0){
    			$key=$this->build_key($id, $group);
    
    			if($this->is_non_persistent_group($group)){
    				$this->add_to_internal_cache($key, $data);
    				return true;
    			}else{
    				$result	= $this->mc->set($key, $data, $expire);
    
    				if($this->mc->getResultCode() === Memcached::RES_SUCCESS){
    					$this->add_to_internal_cache($key, $data);
    				} else{
    					$this->delete_from_internal_cache($key);
    				}
    				
    				return $result;
    			}
    		}
    
    		public function incr($id, $offset=1, $group='default'){
    			$key	= $this->build_key($id, $group);
    
    			$result	= $this->mc->increment($key, $offset);
    
    			if($this->mc->getResultCode() === Memcached::RES_SUCCESS){
    				$this->add_to_internal_cache($key, $result);
    			} else{
    				$this->delete_from_internal_cache($key);
    			}
    
    			return $result;
    		}
    
    		public function decr($id, $offset=1, $group='default'){
    			$key	= $this->build_key($id, $group);
    
    			$result	= $this->mc->decrement($key, $offset);
    
    			if($this->mc->getResultCode() === Memcached::RES_SUCCESS){
    				$this->add_to_internal_cache($key, $result);
    			} else{
    				$this->delete_from_internal_cache($key);
    			}
    
    			return $result;
    		}
    
    		public function delete($id, $group='default'){
    			$key=$this->build_key($id, $group);
    
    			$this->delete_from_internal_cache($key);
    
    			if($this->is_non_persistent_group($group)){
    				return true;
    			}
    
    			return $this->mc->delete($key);
    		}
    
    		public function flush(){
    			$this->cache	= [];
    			return $this->mc->flush();
    		}
    
    		public function get($id, $group='default', $force=false, &$found=null){
    			$key	= $this->build_key($id, $group);
    			
    			if($this->internal_cache_exists($key) && !$force){
    				$found	= true;
    				return $this->get_from_internal_cache($key);
    			}elseif($this->is_non_persistent_group($group)){
    				$found	= false;
    				return false;
    			}
    			
    			$value	= $this->mc->get($key);
    			
    			if($this->mc->getResultCode() == Memcached::RES_NOTFOUND){
    				$found	= false;
    				return false;
    			} else{
    				$found	= true;
    
    				$this->add_to_internal_cache($key, $value);
    
    				return $value;
    			}
    		}
    
    		public function get_multiple($ids, $group='default', $force=false){
    			$caches	= [];
    			$keys	= [];
    
    			foreach($ids as $id){
    				$keys[$id]	= $this->build_key($id, $group);
    			}
    
    			if($this->is_non_persistent_group($group)){
    				foreach($keys as $id=>$key){
    					$caches[$id]	= $this->get_from_internal_cache($key);
    				}
    
    				return $caches;
    			}
    
    			if(!$force){
    				foreach($keys as $id=>$key){
    					if($this->internal_cache_exists($key)){
    						$caches[$id]	= $this->get_from_internal_cache($key);
    					}else{
    						$force	= true;
    						break;
    					}
    				}
    
    				if(!$force){
    					return $caches;
    				}
    			}
    
    			$results	= $this->mc->getMulti(array_values($keys));
    
    			foreach($keys as $id=>$key){
    				if($results && isset($results[$key])){
    					$caches[$id]	= $results[$key];
    					$this->add_to_internal_cache($key, $caches[$id]);
    				}else{
    					$caches[$id]	= false;
    					$this->delete_from_internal_cache($key);
    				}
    			}
    
    			return $caches;
    		}
    
    		public function get_with_cas($id, $group='default', &$cas_token=null){
    			$key	= $this->build_key($id, $group);
    			
    			if(defined('Memcached::GET_EXTENDED')){
    				$result	= $this->mc->get($key, null, Memcached::GET_EXTENDED);
    
    				if($this->mc->getResultCode() == Memcached::RES_NOTFOUND){
    					return false;
    				}else{
    					$cas_token 	= $result['cas'];
    					return $result['value'];
    				}
    			}else{
    				$result	= $this->mc->get($key, null, $cas_token);
    
    				if($this->mc->getResultCode() == Memcached::RES_NOTFOUND){
    					return false;
    				}else{
    					return $result;
    				}
    			}
    		}
    
    		public function cas($cas_token, $id, $data, $group='default', $expire=0){
    			$key=$this->build_key($id, $group);
    
    			if(is_object($data)){
    				$data=clone $data;
    			}
    
    			$this->delete_from_internal_cache($key);
    
    			return $this->mc->cas($cas_token, $key, $data, $expire);
    		}
    
    		public function add_global_groups($groups){
    			$groups	= (array) $groups;
    			$groups	= array_fill_keys($groups, true);
    
    			$this->global_groups	= array_merge($this->global_groups, $groups);
    		}
    
    		public function add_non_persistent_groups($groups){
    			$groups=(array) $groups;
    			$groups	= array_fill_keys($groups, true);
    
    			$this->non_persistent_groups	= array_merge($this->non_persistent_groups, $groups);
    		}
    
    		public function switch_to_blog($blog_id){
    			if(is_multisite()){
    				$blog_id	= intval($blog_id);
    				$this->blog_prefix	= $blog_id . ':';
    			}else{
    				global $table_prefix;
    
    				$this->blog_prefix	= $table_prefix . ':';	
    			}
    		}
    
    		private function internal_cache_exists($key){
    			return $this->cache && isset($this->cache[$key]) && $this->cache[$key] !== false;
    		}
    
    		private function get_from_internal_cache($key){
    			if(!$this->internal_cache_exists($key)){
    				return false;
    			}
    
    			if(is_object($this->cache[$key])){
    				return clone $this->cache[$key];
    			}
    
    			return $this->cache[$key];
    		}
    
    		private function add_to_internal_cache($key, $value){
    			if(is_object($value)){
    				$value	= clone $value;
    			}
    
    			$this->cache[$key]=$value;
    		}
    
    		private function delete_from_internal_cache($key){
    			unset($this->cache[$key]);
    		}
    
    		private function is_non_persistent_group($group){
    			$group	= $group ?: 'default';
    			return isset($this->non_persistent_groups[$group]);
    		}
    
    		private function build_key($id, $group='default'){
    			$group	= $group ?: 'default';
    			$prefix	= isset($this->global_groups[$group]) ? $this->global_prefix : $this->blog_prefix;
    
    			return preg_replace('/\s+/', '', WP_CACHE_KEY_SALT . $prefix . $group . ':' . $id);
    		}
    
    		public function get_stats(){
    			return $this->mc->getStats();
    		}
    
    		public function get_mc(){
    			return $this->mc;
    		}
    
    		public function failure_callback($host, $port){
    		}
    
    		public function close(){
    			$this->mc->quit();
    		}
    
    		public function __construct(){
    
    			$this->mc=new Memcached();
    			$this->mc ->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
    
    			if(!$this->mc->getServerList()){
    				$this->mc->addServer('127.0.0.1', 11211, 100);
    			}
    
    			// global $memcached_servers;
    
    			// if(isset($memcached_servers)){
    			// 	$buckets=$memcached_servers;
    			// } else{
    			// 	$buckets=array('127.0.0.1');
    			// }
    
    			// reset($buckets);
    			// if(is_int(key($buckets))){
    			// 	$buckets=array('default' => $buckets);
    			// }
    
    			// foreach($buckets as $bucket => $servers){
    			// 	$this->mc[ $bucket ]=new Memcached($bucket);
    			// 	$this->mc[ $bucket ] ->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
    
    			// 	if(count($this->mc[ $bucket ]->getServerList())){
    			// 		continue;
    			// 	}
    
    			// 	$instances=array();
    			// 	foreach($servers as $server){
    			// 		@list($node, $port)=explode(':', $server.":");
    			// 		if(empty($port)){
    			// 			$port=ini_get('memcache.default_port');
    			// 		}
    			// 		$port=intval($port);
    			// 		if(! $port){
    			// 			$port=11211;
    			// 		}
    
    			// 		$instances[]=array($node, $port, 1);
    			// 	}
    			// 	$this->mc[ $bucket ]->addServers($instances);
    			// }
    
    			if(is_multisite()){
    				$this->blog_prefix		= get_current_blog_id() . ':';
    				$this->global_prefix	= '';
    			}else{
    				global $table_prefix;
    
    				$this->blog_prefix		= $table_prefix . ':';
    
    				if(defined('CUSTOM_USER_TABLE') && defined('CUSTOM_USER_META_TABLE')){
    					$this->global_prefix	= '';
    				}else{
    					$this->global_prefix	= $table_prefix . ':';	
    				}	
    			}
    
    			// $this->cache_hits   =& $this->stats['get'];
    			// $this->cache_misses =& $this->stats['add'];
    		}
    	}
    }

     

  3. 编辑网站根目录的 wp-config.php 文件,在 define('WP_DEBUG', false); 的下方添加以下代码:

define('WP_CACHE', true);

完成后,WordPress 的 Memcached 缓存功能就启用了。

Memcached缓存功能确认

在浏览器中按下 F12,打开开发者工具,在 Network 选项卡中点击页面请求,在 Response Headers 中查找 X-Cache: HIT 或 X-Cache: MISS,即可判断是否启用了缓存。

PHP查询数据库确认

在 /wp-content/themes/主题/footer.php 中添加以下代码(放在

内):

<?php echo sprintf(__('查询 %s 次,','b2'),get_num_queries()); ?>

<?php echo sprintf(__('耗时 %s 秒','b2'),timer_stop(0,4)); ?>

刷新前端页面,在底部将看到“查询 11 次,耗时 0.4945 秒”之类的信息,说明缓存生效。

如果缓存未生效,可能会看到“查询 326 次,耗时 1.4945 秒”等信息。你可以把 wp-config.php 中的 true 改为 false 或删除 object-cache.php 文件,对比差异。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容