文章目录
-
- [2. OPcache配置:PHP编译缓存极致优化](#2. OPcache配置:PHP编译缓存极致优化)
-
- [2.1 OPcache核心原理](#2.1 OPcache核心原理)
- [2.2 实战配置:php.ini优化参数](#2.2 实战配置:php.ini优化参数)
- [2.3 生效验证与性能监控](#2.3 生效验证与性能监控)
- [2.4 安全防护注意事项](#2.4 安全防护注意事项)
- [3. 数据库查询优化:减轻数据库压力](#3. 数据库查询优化:减轻数据库压力)
-
- [3.1 索引优化:高效查询核心](#3.1 索引优化:高效查询核心)
-
- [3.1.1 适合建索引的场景](#3.1.1 适合建索引的场景)
- [3.1.2 索引优化实战示例](#3.1.2 索引优化实战示例)
- [3.1.3 索引失效场景(避坑)](#3.1.3 索引失效场景(避坑))
- [3.2 查询语句优化实战](#3.2 查询语句优化实战)
-
- [3.2.1 核心优化技巧](#3.2.1 核心优化技巧)
- [3.2.2 EXPLAIN分析慢查询](#3.2.2 EXPLAIN分析慢查询)
- [3.3 连接池配置:减少连接开销](#3.3 连接池配置:减少连接开销)
-
- [3.3.1 PDO连接池实战(PHP原生)](#3.3.1 PDO连接池实战(PHP原生))
- [3.4 慢查询日志与排查](#3.4 慢查询日志与排查)
- [4. Redis缓存集成:提升数据访问速度](#4. Redis缓存集成:提升数据访问速度)
-
- [4.1 Redis集成准备:扩展安装与配置](#4.1 Redis集成准备:扩展安装与配置)
-
- [4.1.1 安装Redis扩展](#4.1.1 安装Redis扩展)
- [4.1.2 Redis基础配置(redis.conf)](#4.1.2 Redis基础配置(redis.conf))
- [4.2 实战封装:Redis缓存工具类](#4.2 实战封装:Redis缓存工具类)
- [4.3 缓存策略:穿透/击穿/雪崩防护](#4.3 缓存策略:穿透/击穿/雪崩防护)
-
- [4.3.1 缓存穿透(查询不存在的数据)](#4.3.1 缓存穿透(查询不存在的数据))
- [4.3.2 缓存击穿(热点数据缓存过期)](#4.3.2 缓存击穿(热点数据缓存过期))
- [4.3.3 缓存雪崩(大量缓存同时过期)](#4.3.3 缓存雪崩(大量缓存同时过期))
- [4.4 Redis安全配置要点](#4.4 Redis安全配置要点)
- [5. 负载均衡部署:高可用架构搭建](#5. 负载均衡部署:高可用架构搭建)
-
- [5.1 负载均衡核心架构](#5.1 负载均衡核心架构)
- [5.2 Nginx负载均衡实战配置](#5.2 Nginx负载均衡实战配置)
-
- [5.2.1 Nginx负载均衡核心配置(nginx.conf)](#5.2.1 Nginx负载均衡核心配置(nginx.conf))
- [5.2.2 PHP-FPM配置(php-fpm.conf)](#5.2.2 PHP-FPM配置(php-fpm.conf))
- [5.3 会话共享:解决分布式session问题](#5.3 会话共享:解决分布式session问题)
-
- [5.3.1 PHP配置session存储到Redis(php.ini)](#5.3.1 PHP配置session存储到Redis(php.ini))
- [5.3.2 代码层验证session共享](#5.3.2 代码层验证session共享)
- [5.4 服务器健康检查配置](#5.4 服务器健康检查配置)
- [6. 总结](#6. 总结)
2. OPcache配置:PHP编译缓存极致优化
OPcache是PHP官方推荐的编译缓存扩展,核心作用是将PHP脚本编译后的字节码缓存到内存中,避免每次请求都重复编译脚本,可使PHP执行效率提升50%以上,是PHP性能优化的"第一步骤"。
2.1 OPcache核心原理
PHP脚本执行流程默认分为三步:1. 读取脚本文件;2. 编译为字节码;3. 执行字节码并返回结果。其中"编译"步骤会消耗大量CPU资源,且同一脚本的编译结果固定不变。
OPcache通过缓存脚本编译后的字节码,跳过重复编译步骤,直接执行缓存中的字节码,同时还会对字节码进行优化(如常量折叠、变量优化),进一步提升执行效率。
2.2 实战配置:php.ini优化参数
PHP 7.0+已内置OPcache扩展,无需额外安装,仅需在php.ini中配置核心参数即可生效。以下是生产环境最优配置(注释清晰,可直接复制):
php
; 开启OPcache扩展
opcache.enable=1
; 仅在CLI模式下开启(可选,用于命令行脚本优化)
opcache.enable_cli=1
; OPcache共享内存大小,根据服务器内存配置(建议至少128M)
opcache.memory_consumption=256
; 存储临时字符串的内存大小(建议64M)
opcache.interned_strings_buffer=64
; 最大缓存的脚本文件数量(建议设置为项目脚本数的1.5倍,默认1000)
opcache.max_accelerated_files=4000
; 缓存的脚本文件过期时间(秒),0表示永不过期,生产环境建议60
opcache.revalidate_freq=60
; 关闭文件时间戳验证(提升性能,修改脚本后需手动重启PHP-FPM生效)
opcache.validate_timestamps=0
; 允许缓存未优化的脚本(建议开启)
opcache.allow_comments=1
opcache.allow_directives=1
; 开启快速关闭,加速PHP进程回收
opcache.fast_shutdown=1
; 开启字节码预加载(PHP 7.4+特性,进一步提升性能)
opcache.preload=/www/wwwroot/project/preload.php
; 预加载脚本的内存限制(建议32M)
opcache.preload_user=www
补充:preload.php文件用于指定预加载的核心脚本(如框架核心文件),示例内容:
php
<?php
// preload.php
// 预加载Laravel框架核心文件(根据项目框架调整)
$files = [
__DIR__.'/vendor/laravel/framework/src/Illuminate/Foundation/Application.php',
__DIR__.'/vendor/laravel/framework/src/Illuminate/Http/Request.php'
];
foreach ($files as $file) {
if (file_exists($file)) {
opcache_compile_file($file);
}
}
2.3 生效验证与性能监控
配置完成后,重启PHP-FPM使配置生效(命令如下):
bash
# CentOS系统
systemctl restart php-fpm
# Ubuntu系统
service php7.4-fpm restart
验证OPcache是否生效:创建phpinfo.php文件,访问后搜索"OPcache",若显示"Enabled"则说明生效。
php
<?php
phpinfo();
?>
性能监控:通过OPcache内置函数查看缓存状态,可集成到项目监控面板:
php
<?php
// 查看OPcache缓存状态
$status = opcache_get_status();
// 输出缓存命中率(核心指标,建议>95%)
echo "OPcache缓存命中率:".round($status['opcache_statistics']['hit_rate'],2)."%";
// 输出缓存的脚本数量
echo "缓存脚本数:".$status['opcache_statistics']['num_cached_scripts'];
// 输出未缓存的脚本数量
echo "未缓存脚本数:".$status['opcache_statistics']['num_uncached_scripts'];
?>
2.4 安全防护注意事项
-
关闭opcache.validate_timestamps后,修改脚本需重启PHP-FPM,避免恶意修改脚本后立即生效;
-
限制preload.php文件权限为644,禁止非root用户修改,防止恶意注入代码;
-
避免设置过大的opcache.memory_consumption,防止占用过多内存导致服务器卡顿。
3. 数据库查询优化:减轻数据库压力
数据库是PHP项目的性能瓶颈高发区,80%的页面响应慢问题源于数据库查询优化不足。本节聚焦MySQL数据库,从索引、语句、连接池、慢查询四个维度给出实战方案。
3.1 索引优化:高效查询核心
索引是数据库优化的"基石",合理的索引可使查询速度提升10-100倍,核心原则:高频查询字段建索引、避免过度索引、遵循最左前缀原则。
3.1.1 适合建索引的场景
-
WHERE子句中频繁出现的字段(如用户ID、订单状态);
-
JOIN关联字段(如user.id与order.user_id);
-
排序字段(ORDER BY)、分组字段(GROUP BY);
-
唯一约束字段(如手机号、邮箱,用UNIQUE索引)。
3.1.2 索引优化实战示例
sql
-- 错误:无索引,查询慢
SELECT * FROM order WHERE user_id=100 AND status=1;
-- 正确:创建联合索引(遵循最左前缀原则,高频字段在前)
CREATE INDEX idx_order_userid_status ON `order`(user_id, status);
-- 错误:过度索引(同一字段创建多个索引)
CREATE INDEX idx_user_id ON user(id);
CREATE INDEX idx_user_id2 ON user(id); -- 冗余,需删除
-- 正确:唯一索引(适合唯一字段)
CREATE UNIQUE INDEX idx_user_mobile ON user(mobile);
3.1.3 索引失效场景(避坑)
-
索引字段使用函数(如LEFT(name,2)、DATE(create_time));
-
索引字段使用运算符(如id+1=100、price*2>200);
-
字符串字段未加引号(如mobile=13800138000,实际为varchar类型);
-
OR连接的字段中有未建索引的字段。
3.2 查询语句优化实战
3.2.1 核心优化技巧
sql
-- 错误1:SELECT * 读取冗余字段
SELECT * FROM user WHERE id=100;
-- 正确1:只查询需要的字段
SELECT id, username, mobile FROM user WHERE id=100;
-- 错误2:子查询效率低(适合用JOIN替代)
SELECT * FROM user WHERE id IN (SELECT user_id FROM order WHERE status=1);
-- 正确2:JOIN关联查询(效率更高)
SELECT u.id, u.username FROM user u JOIN `order` o ON u.id=o.user_id WHERE o.status=1;
-- 错误3:LIMIT分页越往后越慢(适合用主键排序)
SELECT * FROM article LIMIT 10000, 10; -- 低效
-- 正确3:主键分页(高效)
SELECT * FROM article WHERE id>10000 LIMIT 10;
-- 错误4:GROUP BY 未排序却用ORDER BY NULL
SELECT user_id, COUNT(*) FROM `order` GROUP BY user_id ORDER BY NULL; -- 无需排序时省略ORDER BY
-- 正确4:按需排序
SELECT user_id, COUNT(*) FROM `order` GROUP BY user_id ORDER BY COUNT(*) DESC;
3.2.2 EXPLAIN分析慢查询
使用EXPLAIN关键字分析查询语句执行计划,定位优化点:
sql
EXPLAIN SELECT u.id, u.username FROM user u JOIN `order` o ON u.id=o.user_id WHERE o.status=1;
-- 关键字段解读:
-- type:连接类型(ALL=全表扫描,ref=索引匹配,eq_ref=唯一索引匹配,system=最优)
-- key:实际使用的索引(NULL表示未使用索引)
-- rows:预估扫描行数(越少越好)
-- Extra:额外信息(Using index=覆盖索引,Using where=过滤条件,Using filesort=文件排序)
3.3 连接池配置:减少连接开销
PHP默认每次请求都会创建新的数据库连接,连接销毁过程会消耗资源。通过数据库连接池复用连接,可减少连接开销,提升并发能力。
3.3.1 PDO连接池实战(PHP原生)
php
<?php
class DBPool {
// 连接池实例
private static $instance;
// 连接池配置
private $config = [
'host' => '127.0.0.1',
'port' => 3306,
'dbname' => 'test',
'username' => 'root',
'password' => '123456',
'charset' => 'utf8mb4',
'pool_size' => 10 // 连接池最大连接数
];
// 连接池容器
private $connections = [];
// 单例模式,禁止外部实例化
private function __construct() {}
private function __clone() {}
// 获取连接池实例
public static function getInstance() {
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
// 获取数据库连接
public function getConnection() {
// 从连接池获取可用连接
foreach ($this->connections as $key => $conn) {
if ($conn->getAttribute(PDO::ATTR_CONNECTION_STATUS) === 'SQLSTATE[08000]: Connection in progress') {
return $conn;
}
}
// 连接池未满,创建新连接
if (count($this->connections) < $this->config['pool_size']) {
$dsn = "mysql:host={$this->config['host']};port={$this->config['port']};dbname={$this->config['dbname']};charset={$this->config['charset']}";
try {
$conn = new PDO($dsn, $this->config['username'], $this->config['password']);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connections[] = $conn;
return $conn;
} catch (PDOException $e) {
throw new Exception("数据库连接失败:".$e->getMessage());
}
}
// 连接池已满,抛出异常(或阻塞等待)
throw new Exception("数据库连接池已满,请稍后再试");
}
// 归还连接到连接池
public function releaseConnection(PDO $conn) {
$key = array_search($conn, $this->connections);
if ($key !== false) {
$this->connections[$key] = $conn;
}
}
}
// 使用示例
$pool = DBPool::getInstance();
$conn = $pool->getConnection();
// 执行查询
$stmt = $conn->query("SELECT id, username FROM user LIMIT 10");
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 归还连接
$pool->releaseConnection($conn);
3.4 慢查询日志与排查
开启MySQL慢查询日志,定位慢查询语句,步骤如下:
bash
# 1. 修改MySQL配置文件(my.cnf)
[mysqld]
# 开启慢查询日志
slow_query_log=1
# 慢查询日志存储路径
slow_query_log_file=/var/lib/mysql/slow.log
# 查询时间超过1秒视为慢查询(生产环境建议0.5秒)
long_query_time=1
# 记录未使用索引的查询
log_queries_not_using_indexes=1
# 2. 重启MySQL生效
systemctl restart mysqld
# 3. 分析慢查询日志(使用mysqldumpslow工具)
# 查看最耗时的10条慢查询
mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log
# 查看最多访问的10条慢查询
mysqldumpslow -s c -t 10 /var/lib/mysql/slow.log
4. Redis缓存集成:提升数据访问速度
Redis作为高性能的内存数据库,可将高频访问数据(如首页热点数据、用户信息、商品详情)缓存到内存中,减少数据库查询压力,提升数据访问速度。本节涵盖集成配置、工具类封装、缓存策略与安全防护。
4.1 Redis集成准备:扩展安装与配置
4.1.1 安装Redis扩展
bash
# 方法1:通过pecl安装(推荐)
pecl install redis
# 方法2:手动编译安装(适合无pecl环境)
wget https://pecl.php.net/get/redis-5.3.7.tgz
tar -zxvf redis-5.3.7.tgz
cd redis-5.3.7
phpize
./configure --with-php-config=/usr/bin/php-config
make && make install
# 配置php.ini,添加扩展
echo "extension=redis.so" >> /etc/php.ini
# 重启PHP-FPM生效
systemctl restart php-fpm
4.1.2 Redis基础配置(redis.conf)
bash
# 绑定IP(生产环境建议绑定内网IP,如192.168.1.100)
bind 127.0.0.1 192.168.1.100
# 设置密码(必填,防止未授权访问)
requirepass your_strong_password
# 端口(默认6379,可修改为自定义端口)
port 6379
# 最大内存限制(建议设置为服务器内存的50%)
maxmemory 4gb
# 内存淘汰策略(内存满时删除最少使用的缓存)
maxmemory-policy allkeys-lru
# 禁止公网访问危险命令(如flushall、config)
rename-command FLUSHALL ""
rename-command CONFIG ""
rename-command FLUSHDB ""
4.2 实战封装:Redis缓存工具类
封装Redis工具类,统一管理缓存操作,支持缓存设置、获取、删除、过期时间设置,适配生产环境:
php
<?php
class RedisCache {
// Redis实例
private static $redis;
// 配置信息
private static $config = [
'host' => '127.0.0.1',
'port' => 6379,
'password' => 'your_strong_password',
'timeout' => 3, // 连接超时时间(秒)
'database' => 0, // 选择Redis数据库
'prefix' => 'php_cache_', // 缓存前缀(避免多项目冲突)
];
// 初始化Redis连接
private static function init() {
if (!self::$redis) {
self::$redis = new Redis();
try {
// 连接Redis
self::$redis->connect(self::$config['host'], self::$config['port'], self::$config['timeout']);
// 验证密码
if (!empty(self::$config['password'])) {
self::$redis->auth(self::$config['password']);
}
// 选择数据库
self::$redis->select(self::$config['database']);
// 设置序列化方式(JSON比serialize更安全,避免反序列化漏洞)
self::$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_JSON);
} catch (RedisException $e) {
throw new Exception("Redis连接失败:".$e->getMessage());
}
}
return self::$redis;
}
// 设置缓存($expire为过期时间,单位秒,0表示永不过期)
public static function set($key, $value, $expire = 0) {
$redis = self::init();
$key = self::$config['prefix'] . $key;
if ($expire > 0) {
return $redis->setex($key, $expire, $value);
} else {
return $redis->set($key, $value);
}
}
// 获取缓存
public static function get($key) {
$redis = self::init();
$key = self::$config['prefix'] . $key;
return $redis->get($key);
}
// 删除缓存
public static function del($key) {
$redis = self::init();
$key = self::$config['prefix'] . $key;
return $redis->del($key);
}
// 缓存自增(适合计数器)
public static function incr($key, $step = 1) {
$redis = self::init();
$key = self::$config['prefix'] . $key;
return $redis->incrBy($key, $step);
}
// 缓存自减
public static function decr($key, $step = 1) {
$redis = self::init();
$key = self::$config['prefix'] . $key;
return $redis->decrBy($key, $step);
}
// 批量获取缓存
public static function mget($keys) {
$redis = self::init();
$prefixKeys = array_map(function($k) {
return self::$config['prefix'] . $k;
}, $keys);
return $redis->mget($prefixKeys);
}
// 设置缓存过期时间
public static function expire($key, $expire) {
$redis = self::init();
$key = self::$config['prefix'] . $key;
return $redis->expire($key, $expire);
}
}
// 使用示例
// 设置缓存(2小时过期)
RedisCache::set('user_100', ['id'=>100, 'username'=>'test'], 7200);
// 获取缓存
$user = RedisCache::get('user_100');
// 删除缓存
RedisCache::del('user_100');
// 计数器自增
RedisCache::incr('article_view_100');
4.3 缓存策略:穿透/击穿/雪崩防护
4.3.1 缓存穿透(查询不存在的数据)
问题:恶意查询不存在的数据,导致缓存失效,直接穿透到数据库,引发数据库压力过大。
解决方案:缓存空值+布隆过滤器
php
<?php
// 缓存空值示例
function getUserById($id) {
// 先查缓存
$user = RedisCache::get("user_$id");
if ($user !== false) {
return $user === 'null' ? null : $user;
}
// 缓存未命中,查数据库
$user = DB::query("SELECT * FROM user WHERE id=?", [$id]);
if ($user) {
// 缓存真实数据(2小时过期)
RedisCache::set("user_$id", $user, 7200);
} else {
// 缓存空值(10分钟过期,避免长期缓存空值)
RedisCache::set("user_$id", 'null', 600);
}
return $user;
}
4.3.2 缓存击穿(热点数据缓存过期)
问题:热点数据缓存过期瞬间,大量请求穿透到数据库,导致数据库压力突增。
解决方案:互斥锁+热点数据永不过期
php
<?php
// 互斥锁示例
function getHotArticle($id) {
// 先查缓存
$article = RedisCache::get("article_$id");
if ($article) {
return $article;
}
// 缓存未命中,获取互斥锁
$lockKey = "lock_article_$id";
$lock = RedisCache::get($lockKey);
if (!$lock) {
// 获取锁成功,查数据库并更新缓存
RedisCache::set($lockKey, 1, 3); // 锁3秒过期,避免死锁
$article = DB::query("SELECT * FROM article WHERE id=?", [$id]);
if ($article) {
RedisCache::set("article_$id", $article, 86400); // 缓存1天
} else {
RedisCache::set("article_$id", 'null', 600);
}
// 释放锁
RedisCache::del($lockKey);
return $article;
} else {
// 获取锁失败,重试(间隔100ms)
usleep(100000);
return getHotArticle($id);
}
}
4.3.3 缓存雪崩(大量缓存同时过期)
问题:同一时间大量缓存过期,导致大量请求穿透到数据库,引发数据库雪崩。
解决方案:缓存过期时间加随机值+分层缓存
php
<?php
// 缓存过期时间加随机值示例
function setCacheWithRandomExpire($key, $value, $baseExpire = 86400) {
// 过期时间 = 基础时间 + 随机时间(0-3600秒),避免同时过期
$expire = $baseExpire + rand(0, 3600);
RedisCache::set($key, $value, $expire);
}
// 分层缓存示例(本地缓存+Redis缓存)
function getCategoryData() {
// 先查本地缓存(APC/OPcache)
if (apc_exists('category_data')) {
return apc_fetch('category_data');
}
// 再查Redis缓存
$data = RedisCache::get('category_data');
if ($data) {
// 写入本地缓存(10分钟过期)
apc_store('category_data', $data, 600);
return $data;
}
// 查数据库并更新缓存
$data = DB::query("SELECT * FROM category");
RedisCache::set('category_data', $data, 86400 + rand(0, 3600));
apc_store('category_data', $data, 600);
return $data;
}
4.4 Redis安全配置要点
-
必须设置密码(requirepass),密码长度不少于12位,包含字母、数字、特殊字符;
-
绑定内网IP(bind),禁止公网访问Redis端口(6379);
-
重命名/禁用危险命令(FLUSHALL、CONFIG、FLUSHDB);
-
限制Redis最大内存(maxmemory),避免占用过多服务器内存;
-
启用Redis持久化(AOF+RDB),防止缓存丢失。
5. 负载均衡部署:高可用架构搭建
当单台服务器无法承载业务并发时,需通过负载均衡将请求分发到多台服务器,提升系统并发能力与可用性。本节采用「Nginx+PHP-FPM+多台应用服务器」架构,实现负载均衡部署。
5.1 负载均衡核心架构
架构示意图(文字描述):用户请求 → Nginx负载均衡器 → 多台PHP应用服务器(PHP-FPM) → 共享数据库/Redis
核心组件说明:
-
Nginx:作为负载均衡器,分发请求、处理静态资源、反向代理;
-
PHP应用服务器:多台服务器部署相同的PHP项目,运行PHP-FPM;
-
共享数据库/Redis:多台应用服务器连接同一数据库与Redis,保证数据一致性。
5.2 Nginx负载均衡实战配置
5.2.1 Nginx负载均衡核心配置(nginx.conf)
nginx
# 负载均衡配置(http块内)
http {
# 上游服务器集群(应用服务器组)
upstream php_servers {
# 服务器1(权重1,weight越大,分配的请求越多)
server 192.168.1.101:9000 weight=1 max_fails=3 fail_timeout=30s;
# 服务器2(权重1)
server 192.168.1.102:9000 weight=1 max_fails=3 fail_timeout=30s;
# 服务器3(权重2,性能更好的服务器可设置更高权重)
server 192.168.1.103:9000 weight=2 max_fails=3 fail_timeout=30s;
# 负载均衡算法(默认轮询,可选:ip_hash、least_conn)
# ip_hash; # 按用户IP哈希分配,保证同一用户访问同一服务器(解决session问题)
# least_conn; # 按服务器连接数分配,优先分配给连接数少的服务器
}
# 虚拟主机配置(server块内)
server {
listen 80;
server_name www.yourdomain.com;
root /www/wwwroot/project; # 项目根目录(多台服务器需一致)
index index.php index.html;
# 静态资源配置(Nginx直接处理,无需转发到PHP-FPM)
location ~* \.(jpg|jpeg|png|gif|css|js|ico)$ {
root /www/wwwroot/project/public;
expires 7d; # 静态资源缓存7天
add_header Cache-Control "public, max-age=604800";
}
# PHP请求配置(转发到上游服务器集群)
location ~ \.php$ {
root /www/wwwroot/project;
fastcgi_pass php_servers; # 转发到上游服务器集群
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 超时配置
fastcgi_connect_timeout 30s;
fastcgi_send_timeout 30s;
fastcgi_read_timeout 30s;
}
}
}
5.2.2 PHP-FPM配置(php-fpm.conf)
多台应用服务器的PHP-FPM配置需一致,核心参数:
ini
; 监听端口(与Nginx upstream配置一致)
listen = 9000
; 监听地址(绑定内网IP)
listen.address = 192.168.1.101
; 进程池配置
pm = dynamic
pm.max_children = 50 ; 最大进程数
pm.start_servers = 20 ; 启动时进程数
pm.min_spare_servers = 10 ; 最小空闲进程数
pm.max_spare_servers = 30 ; 最大空闲进程数
pm.max_requests = 1000 ; 每个进程处理的最大请求数(避免内存泄漏)
5.3 会话共享:解决分布式session问题
多台应用服务器部署后,默认session存储在本地,会导致用户在不同服务器间切换时session丢失(如登录状态失效)。解决方案:将session存储到Redis中,实现会话共享。
5.3.1 PHP配置session存储到Redis(php.ini)
ini
; 设置session存储处理器为Redis
session.save_handler = redis
; Redis服务器配置(多台应用服务器需一致)
session.save_path = "tcp://127.0.0.1:6379?auth=your_strong_password&database=1"
; session过期时间(与Redis缓存一致)
session.gc_maxlifetime = 86400
; 关闭session自动启动(按需开启)
session.auto_start = 0
5.3.2 代码层验证session共享
php
<?php
// 开启session
session_start();
// 设置session
$_SESSION['user_id'] = 100;
$_SESSION['username'] = 'test';
// 读取session
echo "当前登录用户:".$_SESSION['username'];
// 销毁session
// session_destroy();
5.4 服务器健康检查配置
Nginx默认支持被动健康检查(通过max_fails、fail_timeout参数),也可通过nginx_upstream_check_module模块实现主动健康检查(需编译安装该模块)。
nginx
# 被动健康检查(已在5.2.1配置中包含)
upstream php_servers {
server 192.168.1.101:9000 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.102:9000 weight=1 max_fails=3 fail_timeout=30s;
# max_fails=3:3次请求失败视为服务器不可用
# fail_timeout=30s:30秒内不再分发请求到该服务器,30秒后重新检测
}
# 主动健康检查(需安装nginx_upstream_check_module)
upstream php_servers {
server 192.168.1.101:9000 weight=1;
server 192.168.1.102:9000 weight=1;
check interval=3000 rise=2 fall=3 timeout=1000 type=tcp;
# interval=3000:每3秒检查一次
# rise=2:连续2次检查成功视为服务器可用
# fall=3:连续3次检查失败视为服务器不可用
# timeout=1000:检查超时时间1秒
# type=tcp:TCP类型检查(连接端口)
}
6. 总结
PHP性能调优的核心是「层层优化、攻防结合」------OPcache从脚本编译层提升执行效率,数据库优化从数据存储层减轻压力,Redis缓存从数据访问层提升速度,负载均衡从架构层提升并发与可用性,每一步都需兼顾性能与安全。
实战建议:
-
优先开启OPcache:零成本、高收益,是PHP优化的基础;
-
数据库优化循序渐进:先优化索引与查询语句,再配置连接池与慢查询监控;
-
Redis缓存需规避风险:做好穿透/击穿/雪崩防护,同时配置安全策略;
-
负载均衡按需选择算法:普通业务用轮询,需保持session用ip_hash,高并发用least_conn;
-
持续监控:定期查看OPcache命中率、慢查询日志、Redis内存使用情况,动态调整配置。