Redis 缓存接入实战:给 PHP 网站加一层页面缓存,访问速度立竿见影

很多个人站长都有过这样的经历:网站刚上线时速度飞快,随着文章越写越多、插件越装越杂,页面打开越来越慢,数据库查询越来越吃力。尤其是用了 Typecho、WordPress 这类动态博客系统,每一次访问都要执行几十条甚至上百条 SQL 查询,服务器配置不高的话,CPU 很快就跑满了。这时候很多人第一反应是升级服务器配置,花钱换更高配的机器。其实在升级硬件之前,还有一个成本更低、效果立竿见影的方案,就是引入 Redis 缓存层。

Redis 是一个开源的内存数据库,全称是 Remote Dictionary Server,它把数据存在内存里,读写速度是硬盘的几百倍。对个人网站来说,Redis 最经典的用途就是做缓存:把频繁查询的结果、动态生成的页面、会话数据等放进内存,下次请求直接命中,不用再去查数据库。一台 1 核 1G 的低配服务器,接入 Redis 之后把热点页面缓存起来,扛住之前两三倍的流量完全没问题。

一、Redis 适合缓存什么

在动手安装之前,先想清楚缓存什么,方向错了等于白干。对个人博客来说,值得缓存的有三类数据。第一类是热点页面:首页、热门文章页、归档页这些访问频率最高的页面,整页缓存之后几乎不消耗 PHP 和数据库资源。第二类是高频查询结果:比如文章浏览量、评论数量、标签统计这类每次都要查库的数据,用 Redis 存一份,命中就直接返回。第三类是会话和状态数据:登录状态、验证码、临时 token 之类,Redis 自带过期时间,比存在数据库里方便得多。

个人站长最常用的方案是页面级缓存:第一次有人访问某个页面,PHP 正常渲染完,把最终生成的 HTML 存进 Redis,设置一个过期时间比如 300 秒。过期时间内的后续访问直接读缓存输出,PHP 脚本和数据库完全不用执行。这个方案的优点是改动小、效果好,特别适合文章更新不频繁的个人博客。

二、安装与基础配置

以 Debian/Ubuntu 系统为例,安装 Redis 一条命令就够了。CentOS 系系统用 yum 安装,命令类似。安装完成后先别急着用,把基础配置做好。

# Debian/Ubuntu
apt update && apt install -y redis-server
# CentOS/RHEL
yum install -y redis
# 启动并设置开机自启
systemctl enable redis-server
systemctl start redis-server

Redis 默认监听 127.0.0.1,这个默认值对单机部署来说是安全的,不要随便改成 0.0.0.0 对外监听。如果确实需要远程访问,一定要配合密码认证和防火墙白名单,否则 Redis 裸奔在公网上,很快就会被扫描器盯上,被写入恶意数据甚至被挖矿程序利用。

三、安全设置不能省

很多教程只教安装不教安全,这是个大坑。Redis 至少要做三件事。第一,设置密码:编辑 /etc/redis/redis.conf,找到 requirepass 一行,取消注释并设置一个强密码。第二,关闭危险命令:Redis 4.0 之后可以用 rename-command 把 FLUSHALL、CONFIG 这类高危命令改名或禁用,防止有人通过未授权访问清空你的数据。第三,确认绑定地址:默认 bind 127.0.0.1 保持不变,如果需要对外开放,加上防火墙规则只允许指定 IP 访问。

# /etc/redis/redis.conf 关键配置
requirepass 换成强密码
bind 127.0.0.1
rename-command FLUSHALL ""
rename-command CONFIG ""

改完配置记得重启 Redis 让配置生效,然后用 redis-cli -a 密码 ping 验证一下。这里提醒一句,把密码直接写在命令行里会出现在进程列表里,测试可以,生产环境建议用 redis-cli 进入交互模式后执行 AUTH 命令。

四、PHP 接入 Redis

PHP 项目要用 Redis,先装 phpredis 扩展。Debian/Ubuntu 直接用 apt 装即可,装完确认扩展已加载。不同 PHP 版本的包名略有不同,安装后用 php -m 查看输出里有没有 redis 这一行。

apt install -y php-redis
# 验证扩展加载
php -m | grep redis
# 命令行测试连接
php -r "echo (new Redis())->connect('127.0.0.1', 6379) ? 'OK' : 'FAIL';"

连接测试通过之后,就可以在代码里使用 Redis 了。核心思路是读写之前先查缓存,命中就直接返回,没命中再查数据库并把结果写回缓存,同时设置过期时间。下面这段伪代码是缓存的标准套路,几乎所有缓存场景都是这个模式。

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('你的密码');

$key = 'article:' . $articleId;
$data = $redis->get($key);
if ($data === false) {
    // 缓存未命中,查数据库
    $data = query_database($articleId);
    // 写回缓存,3600 秒过期
    $redis->setex($key, 3600, $data);
}
echo $data;

用 Typecho 的站长,可以直接在主题的入口文件里做整页缓存:把渲染完成的 HTML 用一个以请求 URI 为 key 的缓存存起来,过期时间设成 5 到 10 分钟。文章发布或编辑时调用清理函数,把相关页面的缓存删掉,保证读者看到的始终是最新内容。这样改造之后,页面响应时间通常能从几百毫秒降到几十毫秒,效果非常直观。

五、缓存穿透、击穿与雪崩

用 Redis 做缓存,光会用还不够,还得知道三个经典问题,不然流量一大就要翻车。

第一个是缓存穿透:有人恶意请求一个根本不存在的 ID,比如文章 ID 传负数,每次请求都查不到缓存,全部打到数据库。解决思路是把空结果也缓存起来,设置一个较短的过期时间,比如 60 秒,这样同样的非法请求第二次就命中缓存了。

第二个是缓存击穿:某个热点 key 恰好到了过期时间,一瞬间大量请求同时发现缓存没有,一起涌向数据库。解决办法有两个,一是把热点数据的过期时间加一个随机值,避免集中在同一秒过期;二是在代码里加互斥锁,只有一个请求去查库,其余请求等待。

第三个是缓存雪崩:大量 key 在同一时间过期,或者 Redis 服务挂了,导致全部请求直接打到数据库。应对办法:过期时间加随机扰动;Redis 做持久化并配置主从,挂了一台能顶上;代码层面加降级开关,Redis 不可用时直接回源查库,不让网站整体挂掉。

六、缓存运维小技巧

最后分享几个日常运维里用得上的小技巧。查看内存占用用 redis-cli info memory;查看当前有哪些 key 用 redis-cli keys 加通配符,但生产环境 keys 命令要慎用,量大时会阻塞,改用 scan 命令分批遍历。定期用 redis-cli save 或依赖自动 RDB 持久化做好数据备份。清理缓存不要用 FLUSHALL 全清,除非是测试环境,线上建议精确删 key 或者按前缀批量删除。

还要提醒一点:Redis 占的是内存,1G 内存的服务器给 Redis 分配 128M 到 256M 就够个人站用了,不要贪多。设置 maxmemory 上限和内存淘汰策略,防止 Redis 把服务器内存吃光导致 OOM。

再说说持久化。Redis 默认开启 RDB 快照持久化,会定期把内存数据写入磁盘的 dump.rdb 文件,服务器重启后数据还能恢复。如果你的缓存数据丢了也无所谓,用默认配置就行;如果缓存里存了计数、队列这类不想丢的数据,可以再开启 AOF 追加日志。注意持久化文件要放在非网站目录,并设置好文件权限,防止被 Web 服务读到。日常监控用 redis-cli info memory 看 used_memory 和 maxmemory 的比值,发现内存增长异常就排查一下是不是有 key 没有设置过期时间——这是缓存把内存写满的最常见原因,排查命令用 redis-cli 的 scan 加 type 参数遍历一下 key 的过期情况就能定位。

七、总结

Redis 缓存是个人站长性价比最高的性能优化手段之一,不需要升级服务器,不需要改架构,装好扩展、写好缓存逻辑就能看到明显效果。记住几个要点:先想清楚缓存什么,安全配置一步不能省,处理好穿透击穿雪崩三个坑,控制好内存占用。把这套做完,你的网站在同样的服务器配置下,能稳稳地多扛几倍的访问量。

Last modification:August 16th, 2026 at 08:14 am

Leave a Comment