本文目录导读:

- 使用符号链接(Symbolic Link)切换
- 使用 OPcache 配合 APCu 预加载
- 使用部署工具(如 Deployer、Envoy)
- 蓝绿部署 / 金丝雀发布(容器化场景)
- 数据库迁移的原子性
- 推荐方案
在 PHP 项目的原子部署(Atomic Deployment)中,核心目标是在用户无感知的前提下完成版本更新,避免出现“部分文件已更新、部分文件未更新”导致的代码不一致问题,下面是几种常见的 PHP 原子部署实现方式:
使用符号链接(Symbolic Link)切换
这是最经典的原子部署方式,适用于绝大多数 PHP 项目(如 Laravel、ThinkPHP、原生项目等)。
结构示例
/var/www/
├── releases/
│ ├── 20240501_v1.0/
│ │ ├── app/
│ │ ├── vendor/
│ │ └── index.php
│ ├── 20240502_v1.1/
│ │ ├── app/
│ │ ├── vendor/
│ │ └── index.php
│ └── 20240503_v1.2/
│ ├── app/
│ ├── vendor/
│ └── index.php
└── current -> /var/www/releases/20240503_v1.2/
部署步骤
-
准备新版本
将代码部署到新的目录,如releases/20240504_v1.3/ -
安装依赖、构建
在该目录内执行composer install、npm build等操作(不影响当前运行版本) -
切换符号链接
ln -sfn /var/www/releases/20240504_v1.3 /var/www/current
-
重启 PHP-FPM(可选)
有些框架(如 Laravel)需要清除 OPcache,可用opcache_reset()或执行:kill -USR2 $(pgrep php-fpm)
优势
- 切换瞬间完成,无停机时间
- 用户请求不会看到「半更新」状态
注意
- 共享目录如
storage/、uploads/建议放在符号链接之外,避免被版本覆盖 - 配置文件参数(如
.env)也建议外挂
使用 OPcache 配合 APCu 预加载
变化但 OPcache 未刷新,PHP 仍会执行旧代码,需要确保 OPcache 在部署后及时失效。
实现方式
在部署脚本最末尾执行:
<?php
if (function_exists('opcache_reset')) {
opcache_reset();
}
或通过 Nginx/Apache 访问一个清理脚本:
curl -s http://example.com/clear-cache.php
适合:
- 单服务器或少量服务器
- 不需要零停机
不适合:
- 多服务器集群(需要逐台清理,有短暂不一致风险)
使用部署工具(如 Deployer、Envoy)
这些工具封装了原子部署的逻辑,开箱即用。
示例(Deployer)
host('prod')
->set('deploy_path', '/var/www/project')
->set('repository', 'git@github.com:user/project.git');
task('deploy', [
'deploy:prepare',
'deploy:vendors', // composer install
'deploy:symlink', // ln -sfn 切换
'deploy:cleanup', // 删除旧版本(保留5个)
])->desc('Deploy project');
特点
- 自动创建
releases/结构 - 切换符号链接即原子操作
- 共享目录自动管理(如
storage放shared/目录)
蓝绿部署 / 金丝雀发布(容器化场景)
如果使用 Docker + Kubernetes,原子部署天然实现:
- 蓝绿部署:新版本 Pod 全部就绪后,一次性切换 Service 流量
- 滚动更新:K8s 控制逐步替换 Pod,确保任何时候都有可用的副本
PHP 在容器下的注意事项
- 构建镜像时就将 PHP 文件打包,不 live mount 代码
- 利用
opcache.preload预加载,减少启动开销
数据库迁移的原子性
代码原子部署解决了文件层面的问题,但数据库迁移(如新增字段、改表)也需要原子操作:
- 向下兼容:新代码兼容旧数据库结构(如先加字段,再改代码读新字段)
- 分离部署与迁移:先执行迁移脚本,再切换代码版本
示例流程:
执行数据库迁移(加字段、建索引)
2. 切换代码符号链接
3. 清理旧字段(optional,下个版本再drop)
推荐方案
| 场景 | 方案 |
|---|---|
| 单机 / 低流量 | 符号链接 + OPcache 清理 |
| 多机 / 中等流量 | Deployer / Capistrano + 共享存储 |
| 容器化 / K8s (高流量) |
蓝绿部署 / 滚动更新 |
原子部署的核心口诀:
新代码先就绪,再瞬间切换入口,不信任“在线覆盖复制”。