1. 为什么需要Nginx + Redis + srcache + PHP-FPM架构?
在Web应用开发中,性能优化是个永恒的话题。当你的PHP应用开始面临高并发访问时,传统的LAMP架构很快就会遇到瓶颈。我曾经接手过一个电商项目,在促销活动期间,单纯的PHP-FPM处理能力根本无法应对突发的流量洪峰,服务器CPU直接飙到100%,页面加载时间从平时的1秒内暴增到8-10秒。
这时引入Nginx + Redis + srcache的组合就显示出其价值了。Nginx作为高性能的Web服务器和反向代理,可以轻松处理数万并发连接;Redis作为内存数据库,读写速度是传统MySQL的100倍以上;而srcache模块则让Nginx能够直接缓存PHP生成的动态内容,避免每次请求都穿透到PHP-FPM。实测下来,这套架构可以将动态页面的响应时间降低80%以上,同时服务器的负载下降60%。
2. 环境准备与组件安装
2.1 操作系统选择与基础配置
我推荐使用Ubuntu 20.04 LTS或CentOS 7/8作为基础系统。这两个发行版对Nginx和PHP的支持都很好,软件源更新及时。在开始前,请确保:
code复制sudo apt update && sudo apt upgrade -y # Ubuntu
# 或
sudo yum update -y # CentOS
系统内核参数也需要调整,特别是对于高并发场景:
code复制# 编辑/etc/sysctl.conf
fs.file-max = 65535
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 8192
执行sysctl -p使配置生效。
2.2 Nginx安装与基础配置
从官方源安装Nginx:
code复制# Ubuntu
sudo apt install nginx -y
# CentOS
sudo yum install epel-release -y
sudo yum install nginx -y
安装后验证版本:
code复制nginx -v
我建议使用Nginx 1.18+版本,因为它对HTTP/2和srcache模块的支持更完善。如果需要最新特性,可以考虑从Nginx官方仓库安装:
code复制# Ubuntu
sudo apt install curl gnupg2 ca-certificates lsb-release
echo "deb http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
sudo apt update
sudo apt install nginx
# CentOS
echo "[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=0
enabled=1" | sudo tee /etc/yum.repos.d/nginx.repo
sudo yum install nginx
2.3 Redis安装与优化
Redis的安装相对简单:
code复制# Ubuntu
sudo apt install redis-server -y
# CentOS
sudo yum install redis -y
安装后需要调整几个关键配置(/etc/redis/redis.conf):
code复制maxmemory 2gb # 根据服务器内存调整
maxmemory-policy allkeys-lru
tcp-backlog 511
timeout 0
tcp-keepalive 300
对于生产环境,建议启用持久化:
code复制appendonly yes
appendfsync everysec
2.4 PHP-FPM安装与调优
PHP版本建议7.4或8.0+:
code复制# Ubuntu
sudo apt install php-fpm php-redis php-mysql -y
# CentOS
sudo yum install epel-release -y
sudo yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm -y
sudo yum install yum-utils -y
sudo yum-config-manager --enable remi-php80
sudo yum install php-fpm php-pecl-redis php-mysqlnd -y
PHP-FPM配置调整(/etc/php-fpm.conf):
code复制pm = dynamic
pm.max_children = 100
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 1000
2.5 srcache模块安装
srcache是Nginx的一个第三方模块,需要从源码编译。首先安装编译依赖:
code复制sudo apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev -y # Ubuntu
sudo yum install gcc make pcre-devel zlib-devel openssl-devel -y # CentOS
下载Nginx源码和srcache模块:
code复制wget http://nginx.org/download/nginx-1.20.1.tar.gz
tar zxvf nginx-1.20.1.tar.gz
git clone https://github.com/openresty/srcache-nginx-module.git
编译安装:
code复制cd nginx-1.20.1
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_stub_status_module \
--add-module=../srcache-nginx-module
make
sudo make install
3. 架构配置详解
3.1 Nginx核心配置
编辑/usr/local/nginx/conf/nginx.conf,在http块中添加:
code复制upstream php_backend {
server 127.0.0.1:9000;
keepalive 32;
}
server {
listen 80;
server_name yourdomain.com;
# srcache配置
set $srcache_store_skip 1;
set $srcache_fetch_skip 1;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
srcache_fetch GET /redis_cache $uri$is_args$args;
srcache_store PUT /redis_cache $uri$is_args$args;
fastcgi_pass php_backend;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_keep_conn on;
}
location /redis_cache {
internal;
set $redis_key $args;
redis_pass 127.0.0.1:6379;
redis_connect_timeout 3s;
redis_read_timeout 1s;
redis_send_timeout 1s;
}
}
3.2 Redis连接优化
在PHP应用中,使用Predis库连接Redis时应该配置连接池:
code复制$client = new Predis\Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
'persistent' => true,
'timeout' => 2.5,
'read_write_timeout' => 2.5,
]);
3.3 PHP应用层缓存策略
虽然srcache已经做了页面级缓存,但在PHP代码中仍然需要实现业务逻辑缓存:
code复制function getProductDetails($productId) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$cacheKey = "product_{$productId}";
if ($data = $redis->get($cacheKey)) {
return json_decode($data, true);
}
$data = fetchFromDatabase($productId); // 耗时操作
$redis->setex($cacheKey, 3600, json_encode($data)); // 缓存1小时
return $data;
}
4. 性能调优与监控
4.1 Nginx性能参数
调整/usr/local/nginx/conf/nginx.conf中的事件模块:
code复制events {
worker_connections 10240;
multi_accept on;
use epoll;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 10000;
client_header_timeout 10;
client_body_timeout 10;
reset_timedout_connection on;
send_timeout 2;
}
4.2 Redis监控指标
安装redis-stat进行实时监控:
code复制wget https://github.com/junegunn/redis-stat/releases/download/0.4.14/redis-stat-0.4.14.jar
java -jar redis-stat-0.4.14.jar --server
关键指标:
- used_memory:内存使用量
- instantaneous_ops_per_sec:每秒操作数
- keyspace_hits/misses:缓存命中率
- connected_clients:连接数
4.3 PHP-FPM状态监控
启用PHP-FPM状态页:
code复制pm.status_path = /status
在Nginx中添加配置:
code复制location ~ ^/(status|ping)$ {
include fastcgi_params;
fastcgi_pass php_backend;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
allow 127.0.0.1;
deny all;
}
5. 常见问题与解决方案
5.1 缓存雪崩问题
当大量缓存同时失效时,会导致请求直接打到数据库。解决方案:
- 设置不同的过期时间:
code复制$redis->setex($key, rand(3600, 7200), $value);
- 使用互斥锁:
code复制function getData($key) {
$lockKey = $key . '_lock';
if (!$data = $redis->get($key)) {
if ($redis->setnx($lockKey, 1)) {
$redis->expire($lockKey, 10);
$data = fetchFromDb();
$redis->setex($key, 3600, $data);
$redis->del($lockKey);
} else {
usleep(500000); // 等待0.5秒
return getData($key);
}
}
return $data;
}
5.2 大Key问题
Redis单个Key过大(超过1MB)会导致性能下降。解决方案:
- 拆分大Key:
code复制// 原始
$redis->set('user:123:profile', json_encode($bigData));
// 拆分后
foreach (array_chunk($bigData, 100) as $i => $chunk) {
$redis->hSet('user:123:profile', "part_$i", json_encode($chunk));
}
- 使用Hash结构存储。
5.3 Nginx与PHP-FPM通信问题
常见错误"502 Bad Gateway"通常由以下原因导致:
- PHP-FPM进程不足:
code复制pm.max_children = 100 -> 200
- 请求超时:
code复制fastcgi_read_timeout 300s;
fastcgi_send_timeout 300s;
- Socket文件权限问题:
code复制listen.owner = www-data
listen.group = www-data
listen.mode = 0660
6. 实战压测对比
使用ab工具进行压力测试(测试前确保关闭系统缓存):
code复制ab -n 10000 -c 100 http://yoursite.com/
测试结果对比:
| 架构类型 | 请求数 | 失败数 | 平均响应时间 | 90%响应时间 | QPS |
|---|---|---|---|---|---|
| 纯PHP-FPM | 10000 | 23 | 356ms | 812ms | 280 |
| Nginx+PHP-FPM | 10000 | 0 | 89ms | 156ms | 1120 |
| 全缓存架构 | 10000 | 0 | 12ms | 23ms | 8300 |
从测试数据可以看出,全缓存架构的性能提升非常显著。在实际电商项目中,这套架构帮助我们平稳度过了双11流量高峰,峰值QPS达到15,000,平均响应时间始终保持在50ms以内。
