WordPress 使用 Redis 缓存来进行站点加速

109

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

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

WordPress 使用 Redis 缓存来进行站点加速

安装 Redis

如果你使用的是 Debian 或者衍生的操作系统可使用如下命令安装 Redis:
[cce]apt-get install redis-server[/cce]

使用 Predis 作为 Redis 的 PHP 客户端

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

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

前端缓存的 PHP 脚本

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

[cce_php]
<?php
$cf = 1;			// set to 1 if you are using cloudflare
$debug = 0;			// set to 1 if you wish to see execution time and cache actions
$display_powered_by_redis = 1;  // set to 1 if you want to display a powered by redis message with execution time, see below

$start = microtime();   // start timing page exec

// if cloudflare is enabled
if ($cf) {
    if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
        $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
    }
}

// from wp
define('WP_USE_THEMES', true);

// init predis
include("predis.php");
$redis = new Predis\Client('');

// init vars
$domain = $_SERVER['HTTP_HOST'];
$url = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$url = str_replace('?r=y', '', $url);
$url = str_replace('?c=y', '', $url);
$dkey = md5($domain);
$ukey = md5($url);

// check if page isn't a comment submission
(isset($_SERVER['HTTP_CACHE_CONTROL']) && $_SERVER['HTTP_CACHE_CONTROL'] == 'max-age=0') ? $submit = 1 : $submit = 0;

// check if logged in to wp
$cookie = var_export($_COOKIE, true);
$loggedin = preg_match("/wordpress_logged_in/", $cookie);

// check if a cache of the page exists
if ($redis->hexists($dkey, $ukey) && !$loggedin && !$submit && !strpos($url, '/feed/')) {

    echo $redis->hget($dkey, $ukey);
    $cached = 1;
    $msg = 'this is a cache';

// if a comment was submitted or clear page cache request was made delete cache of page
} else if ($submit || substr($_SERVER['REQUEST_URI'], -4) == '?r=y') {

    require('./wp-blog-header.php');
    $redis->hdel($dkey, $ukey);
    $msg = 'cache of page deleted';

// delete entire cache, works only if logged in
} else if ($loggedin && substr($_SERVER['REQUEST_URI'], -4) == '?c=y') {

    require('./wp-blog-header.php');
    if ($redis->exists($dkey)) {
        $redis->del($dkey);
        $msg = 'domain cache flushed';
    } else {
        $msg = 'no cache to flush';
    }

// if logged in don't cache anything
} else if ($loggedin) {

    require('./wp-blog-header.php');
    $msg = 'not cached';

// cache the page
} else {

    // turn on output buffering
    ob_start();

    require('./wp-blog-header.php');

    // get contents of output buffer
    $html = ob_get_contents();

    // clean output buffer
    ob_end_clean();
    echo $html;

    // Store to cache only if the page exist and is not a search result.
    if (!is_404() && !is_search()) {
        // store html contents to redis cache
        $redis->hset($dkey, $ukey, $html);
        $msg = 'cache is set';
    }
}

$end = microtime(); // get end execution time

// show messages if debug is enabled
if ($debug) {
    echo $msg.': ';
    echo t_exec($start, $end);
}

if ($cached && $display_powered_by_redis) {
	// You should move this CSS to your CSS file and change the: float:right;margin:20px 0;
	echo "<style>#redis_powered{float:right;margin:20px 0;background:url(http://images.staticjw.com/jim/3959/redis.png) 10px no-repeat #fff;border:1px solid #D7D8DF;padding:10px;width:190px;}
	#redis_powered div{width:190px;text-align:right;font:10px/11px arial,sans-serif;color:#000;}</style>";
	echo "<a href=\"http://www.aips.me/wordpress-with-redis-as-a-frontend-cache/\" style=\"text-decoration:none;\"><div id=\"redis_powered\"><div>Page generated in<br/> ".t_exec($start, $end)." sec</div></div></a>";
}

// time diff
function t_exec($start, $end) {
    $t = (getmicrotime($end) - getmicrotime($start));
    return round($t,5);
}

// get time
function getmicrotime($t) {
    list($usec, $sec) = explode(" ",$t);
    return ((float)$usec + (float)$sec);
}

?>
[/cce_php]

你也可以在 Github 上查看 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 秒

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

其他建议

本文作者的 WordPress 环境是 Nginx + PHP-FPM + APC + Cloudflare + Redis. 安装在一个 VPS 中,无缓存插件。

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

访问 wp-admin

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

 

本文其实在国内已经有很翻译过了,但我看到作者也一直在更新此文,反而国内译者都不怎么更新,我就自己去重新折腾了一遍。
本文英文原文:http://www.jimwestergren.com/wordpress-with-redis-as-a-frontend-cache/

如果你有设计或者 WordPress 方面的项目需求,可以和我联系 Email:wwwzhouliang@gmail.com。

作者主页 邮箱 微博 腾讯微博 QQ Twitter Facebook Google+

共 109 条评论

  1. 四四 回复

    服务器没有固定ip呢

    1. 周良 (文章作者) 回复

      额,没有固定IP?你是怎么做到的?

      1. 四四 回复

        我们可能不定期更换CDN的IP,请勿使用A记录解析(使用A记录导致打不开后果自负)!主机说的..

        1. 周良 (文章作者) 回复

          噗。。。你这是什么主机?(足迹没办法用这个,你只有服务器/vps才可以用)难道是SAE或者BAE?

          1. 四四 回复

            哦..懂了..

            1. 周良 (文章作者) 回复

              我不建议你用经常更换ip的服务器。还有,CDN的IP更换,和服务器没关系啊,不过也要看你CDN是干嘛的,静态文件用CDN什么的就可以了

  2. 四四 回复

    服务器没有固定ip呢

    1. 周良 (文章作者) 回复

      额,没有固定IP?你是怎么做到的?

      1. 四四 回复

        我们可能不定期更换CDN的IP,请勿使用A记录解析(使用A记录导致打不开后果自负)!主机说的..

        1. 周良 (文章作者) 回复

          噗。。。你这是什么主机?(足迹没办法用这个,你只有服务器/vps才可以用)难道是SAE或者BAE?

          1. 四四 回复

            哦..懂了..

            1. 周良 (文章作者) 回复

              我不建议你用经常更换ip的服务器。还有,CDN的IP更换,和服务器没关系啊,不过也要看你CDN是干嘛的,静态文件用CDN什么的就可以了

  3. STAN 回复

    说实话 没觉得加速

    1. 周良 (文章作者) 回复

      你用了么?

  4. STAN 回复

    说实话 没觉得加速

    1. 周良 (文章作者) 回复

      你用了么?

  5. 余贤康 回复

    要VPS才能用吗?虚拟主机可以吗?

    1. 周良 (文章作者) 回复

      虚拟主机服务器都配置好的,当然没办法用。换VPS吧,可以找我来买...

      1. 余贤康 回复

        没钱。。。

        1. 周良 (文章作者) 回复

          好吧。。。其实VPS很便宜

  6. 余贤康 回复

    要VPS才能用吗?虚拟主机可以吗?

    1. 周良 (文章作者) 回复

      虚拟主机服务器都配置好的,当然没办法用。换VPS吧,可以找我来买...

      1. 余贤康 回复

        没钱。。。

        1. 周良 (文章作者) 回复

          好吧。。。其实VPS很便宜

  7. 奇趣铺 回复

    话说新浪sae开发者怎么认证,需要什么东西

  8. 奇趣铺 回复

    话说新浪sae开发者怎么认证,需要什么东西

  9. 侯永禄 回复

    请问相同URL判断不同设备展示不同页面该如何解决?

Leave a Reply

您的邮箱不会公开,当您的评论有新的回复时,会通过您填写的邮箱向您发送评论内容。 Required fields are marked *

返回顶部