让 WordPress 使用 Redis 缓存来进行加速

Redis 是一个高级的 key-value 存储系统,类似 memcached,所有内容都存在内存中,因此每秒钟可以超过 10 万次 GET 操作。

我下面提出的解决方案是在 Redis 中缓存所有输出的 HTML 内容而无需再让 WordPress 重复执行页面脚本。这里使用 Redis 代替 Varnish 设置简单,而且可能更快。

安装 Redis

如果你使用的是 Debian 或者衍生的操作系统可使用如下命令安装 Redis:

<font face="Courier New">1</font>apt-get install <font face="Courier New">redis-server</font>

或者阅读 安装指南

使用 Predis 作为 Redis 的 PHP 客户端

你需要一个客户端开发包以便 PHP 可以连接到 Redis 服务上。

这里我们推荐 Predis. 上传 predis.php 到 WordPress 的根目录。

前端缓存的 PHP 脚本

步骤1: 在 WordPress 的根目录创建新文件 index-with-redis.php ,内容如下:

 
<font face="Courier New">001</font><font face="Courier New"><?php </font>
<font face="Courier New">002</font><font face="Courier New"> </font> 
<font face="Courier New">003</font><font face="Courier New">// Change these two variables: </font>
<font face="Courier New">004</font><font face="Courier New"> </font> 
<font face="Courier New">005</font><font face="Courier New">$seconds_of_caching</font> = 60*60*24*7; // 7 days.
<font face="Courier New">006</font><font face="Courier New"> </font> 
<font face="Courier New">007</font><font face="Courier New">$ip_of_this_website</font> = '204.62.14.112';
<font face="Courier New">008</font><font face="Courier New"> </font> 
<font face="Courier New">009</font><font face="Courier New">  </font> 
<font face="Courier New">010</font><font face="Courier New"> </font> 
<font face="Courier New">011</font><font face="Courier New">/* </font>
<font face="Courier New">012</font><font face="Courier New"> </font> 
<font face="Courier New">013</font><font face="Courier New">- This file is written by Jim Westergren, copyright all rights reserved. </font>
<font face="Courier New">014</font><font face="Courier New"> </font> 
<font face="Courier New">015</font><font face="Courier New">- See more here: www.jimwestergren.com/wordpress-with-redis-as-a-frontend-cache/ </font>
<font face="Courier New">016</font><font face="Courier New"> </font> 
<font face="Courier New">017</font><font face="Courier New">- The code is free for everyone to use how they want but please mention my name and link to my article when writing about this. </font>
<font face="Courier New">018</font><font face="Courier New"> </font> 
<font face="Courier New">019</font><font face="Courier New">- Change $ip_of_this_website to the IP of your website above. </font>
<font face="Courier New">020</font><font face="Courier New"> </font> 
<font face="Courier New">021</font><font face="Courier New">- Add ?refresh=yes to the end of a URL to refresh it's cache </font>
<font face="Courier New">022</font><font face="Courier New"> </font> 
<font face="Courier New">023</font><font face="Courier New">- You can also enter the redis client via the command prompt with the command "redis-cli" and then remove all cache with the command "flushdb". </font>
<font face="Courier New">024</font><font face="Courier New"> </font> 
<font face="Courier New">025</font><font face="Courier New">*/</font>
<font face="Courier New">026</font><font face="Courier New"> </font> 
<font face="Courier New">027</font><font face="Courier New">  </font> 
<font face="Courier New">028</font><font face="Courier New"> </font> 
<font face="Courier New">029</font><font face="Courier New">// Very necessary if you use Cloudfare: </font>
<font face="Courier New">030</font><font face="Courier New"> </font> 
<font face="Courier New">031</font><font face="Courier New">if</font> (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
<font face="Courier New">032</font><font face="Courier New"> </font> 
<font face="Courier New">033</font>$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
<font face="Courier New">034</font><font face="Courier New"> </font> 
<font face="Courier New">035</font><font face="Courier New">} </font>
<font face="Courier New">036</font><font face="Courier New"> </font> 
<font face="Courier New">037</font><font face="Courier New">  </font> 
<font face="Courier New">038</font><font face="Courier New"> </font> 
<font face="Courier New">039</font><font face="Courier New">// This is from WordPress: </font>
<font face="Courier New">040</font><font face="Courier New"> </font> 
<font face="Courier New">041</font>define('WP_USE_THEMES', true);
<font face="Courier New">042</font><font face="Courier New"> </font> 
<font face="Courier New">043</font><font face="Courier New">  </font> 
<font face="Courier New">044</font><font face="Courier New"> </font> 
<font face="Courier New">045</font><font face="Courier New">// Start the timer: </font>
<font face="Courier New">046</font><font face="Courier New"> </font> 
<font face="Courier New">047</font><font face="Courier New">function</font> getmicrotime($t) {
<font face="Courier New">048</font><font face="Courier New"> </font> 
<font face="Courier New">049</font>list($usec, $sec) = explode(" ",$t);
<font face="Courier New">050</font><font face="Courier New"> </font> 
<font face="Courier New">051</font><font face="Courier New">return</font> ((float)$usec + (float)$sec);
<font face="Courier New">052</font><font face="Courier New"> </font> 
<font face="Courier New">053</font><font face="Courier New">} </font>
<font face="Courier New">054</font><font face="Courier New"> </font> 
<font face="Courier New">055</font><font face="Courier New">$start</font> <font face="Courier New">= microtime(); </font>
<font face="Courier New">056</font><font face="Courier New"> </font> 
<font face="Courier New">057</font><font face="Courier New">  </font> 
<font face="Courier New">058</font><font face="Courier New"> </font> 
<font face="Courier New">059</font><font face="Courier New">// Initiate redis and the PHP client for redis: </font>
<font face="Courier New">060</font><font face="Courier New"> </font> 
<font face="Courier New">061</font>include("predis.php");
<font face="Courier New">062</font><font face="Courier New"> </font> 
<font face="Courier New">063</font><font face="Courier New">$redis</font> = new Predis\Client('');
<font face="Courier New">064</font><font face="Courier New"> </font> 
<font face="Courier New">065</font><font face="Courier New">  </font> 
<font face="Courier New">066</font><font face="Courier New"> </font> 
<font face="Courier New">067</font><font face="Courier New">// few variables: </font>
<font face="Courier New">068</font><font face="Courier New"> </font> 
<font face="Courier New">069</font><font face="Courier New">$current_page_url</font> = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
<font face="Courier New">070</font><font face="Courier New"> </font> 
<font face="Courier New">071</font><font face="Courier New">$current_page_url</font> = str_replace('?refresh=yes', '', $current_page_url);
<font face="Courier New">072</font><font face="Courier New"> </font> 
<font face="Courier New">073</font><font face="Courier New">$redis_key</font> = md5($current_page_url);
<font face="Courier New">074</font><font face="Courier New"> </font> 
<font face="Courier New">075</font><font face="Courier New">  </font> 
<font face="Courier New">076</font><font face="Courier New"> </font> 
<font face="Courier New">077</font><font face="Courier New">// This first case is either manual refresh cache by adding ?refresh=yes after the URL or somebody posting a comment </font>
<font face="Courier New">078</font><font face="Courier New"> </font> 
<font face="Courier New">079</font><font face="Courier New">if</font> (isset($_GET['refresh']) || substr($_SERVER['REQUEST_URI'], -12) == '?refresh=yes' || ($_SERVER['HTTP_REFERER'] == $current_page_url && $_SERVER['REQUEST_URI'] != '/' && $_SERVER['REMOTE_ADDR'] != $ip_of_this_website)) {
<font face="Courier New">080</font><font face="Courier New"> </font> 
<font face="Courier New">081</font>require('./wp-blog-header.php');
<font face="Courier New">082</font><font face="Courier New"> </font> 
<font face="Courier New">083</font>$redis->del($redis_key);
<font face="Courier New">084</font><font face="Courier New"> </font> 
<font face="Courier New">085</font><font face="Courier New">  </font> 
<font face="Courier New">086</font><font face="Courier New"> </font> 
<font face="Courier New">087</font><font face="Courier New">// Second case: cache exist in redis, let's display it </font>
<font face="Courier New">088</font><font face="Courier New"> </font> 
<font face="Courier New">089</font>} else <font face="Courier New">if</font> ($redis->exists($redis_key)) {
<font face="Courier New">090</font><font face="Courier New"> </font> 
<font face="Courier New">091</font><font face="Courier New">$html_of_current_page</font> = $redis->get($redis_key);
<font face="Courier New">092</font><font face="Courier New"> </font> 
<font face="Courier New">093</font><font face="Courier New">echo</font> $html_of_current_page;
<font face="Courier New">094</font><font face="Courier New"> </font> 
<font face="Courier New">095</font><font face="Courier New">echo</font> "<!-- This is cache -->";
<font face="Courier New">096</font><font face="Courier New"> </font> 
<font face="Courier New">097</font><font face="Courier New">  </font> 
<font face="Courier New">098</font><font face="Courier New"> </font> 
<font face="Courier New">099</font><font face="Courier New">// third: a normal visitor without cache. And do not cache a preview page from the wp-admin: </font>
<font face="Courier New">100</font><font face="Courier New"> </font> 
<font face="Courier New">101</font>} else <font face="Courier New">if</font> ($_SERVER['REMOTE_ADDR'] != $ip_of_this_website && strstr($current_page_url, 'preview=true') == false) {
<font face="Courier New">102</font><font face="Courier New"> </font> 
<font face="Courier New">103</font>require('./wp-blog-header.php');
<font face="Courier New">104</font><font face="Courier New"> </font> 
<font face="Courier New">105</font><font face="Courier New">$html_of_current_page</font> = file_get_contents($current_page_url);
<font face="Courier New">106</font><font face="Courier New"> </font> 
<font face="Courier New">107</font>$redis->setex($redis_key, $seconds_of_caching, $html_of_current_page);
<font face="Courier New">108</font><font face="Courier New"> </font> 
<font face="Courier New">109</font><font face="Courier New">echo</font> "<!-- Cache has been set -->";
<font face="Courier New">110</font><font face="Courier New"> </font> 
<font face="Courier New">111</font><font face="Courier New">  </font> 
<font face="Courier New">112</font><font face="Courier New"> </font> 
<font face="Courier New">113</font><font face="Courier New">// last case: the normal WordPress. Should only be called with file_get_contents: </font>
<font face="Courier New">114</font><font face="Courier New"> </font> 
<font face="Courier New">115</font>} else <font face="Courier New">{ </font>
<font face="Courier New">116</font><font face="Courier New"> </font> 
<font face="Courier New">117</font>require('./wp-blog-header.php');
<font face="Courier New">118</font><font face="Courier New"> </font> 
<font face="Courier New">119</font><font face="Courier New">} </font>
<font face="Courier New">120</font><font face="Courier New"> </font> 
<font face="Courier New">121</font><font face="Courier New">  </font> 
<font face="Courier New">122</font><font face="Courier New"> </font> 
<font face="Courier New">123</font><font face="Courier New">  </font> 
<font face="Courier New">124</font><font face="Courier New"> </font> 
<font face="Courier New">125</font><font face="Courier New">// Let's display some page generation time (note: CloudFlare may strip out comments): </font>
<font face="Courier New">126</font><font face="Courier New"> </font> 
<font face="Courier New">127</font><font face="Courier New">$end</font> <font face="Courier New">= microtime(); </font>
<font face="Courier New">128</font><font face="Courier New"> </font> 
<font face="Courier New">129</font><font face="Courier New">$t2</font> = (getmicrotime($end) - getmicrotime($start));
<font face="Courier New">130</font><font face="Courier New"> </font> 
<font face="Courier New">131</font><font face="Courier New">if</font> ($_SERVER['REMOTE_ADDR'] != $ip_of_this_website) {
<font face="Courier New">132</font><font face="Courier New"> </font> 
<font face="Courier New">133</font><font face="Courier New">echo</font> "<!-- Cache system by Jim Westergren. Page generated in ".round($t2,5)." seconds. -->";
<font face="Courier New">134</font><font face="Courier New"> </font> 
<font face="Courier New">135</font><font face="Courier New">} </font>
<font face="Courier New">136</font><font face="Courier New"> </font> 
<font face="Courier New">137</font><font face="Courier New">?></font>

或者直接下载 index-with-redis.php

步骤2:将上述代码中的 IP 地址替换成你网站的 IP 地址

步骤3:在 .htaccess 中将所有出现 index.php 的地方改为 index-with-redis.php ,如果你使用的是 Nginx 则修改 nginx.conf 中的 index.php 为 index-with-redis.php(并重载 Nginx : killall -s HUP nginx)。

性能测试

  • 没有 Redis 的情况下,平均首页执行 1.614 秒,文章页 0.174 秒(无任何缓存插件)
  • 使用 Redis 的情况下,平均页面执行时间 0.00256 秒

我已经在我的博客中使用了如上的方法进行加速很长时间了,一切运行良好。

其他建议

我的环境是 Nginx + PHP-FPM + APC + Cloudflare + Redis. 安装在一个 nano VPS 中,无缓存插件。

请确认使用了 gzip 压缩,可加快访问速度。

访问 wp-admin

要访问 wp-admin 必须使用 /wp-admin/index.php 代替原来的 /wp-admin/.

相关推荐