更新Model前运行migration的无停机单批次部署方案咨询
可行方案:单批次推送+无停机部署实现
完全可以通过单批次推送完成全部操作,搭配git触发器可以实现全程无停机运行,具体实现方案如下:
一、整体执行逻辑
不需要二次推送代码,所有逻辑一次性提交到仓库即可,核心是通过git触发器控制生产端的执行顺序,确保迁移完成前不会调用新增字段。
二、具体操作步骤
1. 开发端提交3部分代码
- 新增
sequence列的migration迁移文件 - 带Redis判断逻辑的Model代码
- (可选)统一的部署执行脚本
2. 生产端配置git触发器(post-receive钩子)
在生产端托管代码的git裸仓库hooks目录下,新建post-receive文件并赋予执行权限,示例内容如下:
#!/bin/bash # 切换到项目根目录 cd /www/your_project_path # 拉取最新代码,此时Model更新但Redis标记不存在,不会调用sequence字段,业务无影响 git pull origin main # 强制执行迁移(生产环境跳过交互确认) php artisan migrate --force # 平滑重启PHP服务,根据实际运行的服务调整(常驻内存框架必须执行,FPM模式可省略) systemctl reload php-fpm
3. 迁移文件补充Redis标记逻辑
在新增sequence列的迁移文件中,新增Redis标记的设置/删除逻辑,确保迁移完成后标记自动生效:
public function up() { Schema::table('你的表名', function (Blueprint $table) { $table->unsignedInteger('sequence')->default(0)->after('product_id'); }); // 迁移执行成功后自动设置标记 Redis::set('product_operations_sequence_added', 1); } public function down() { Schema::table('你的表名', function (Blueprint $table) { $table->dropColumn('sequence'); }); // 回滚时自动删除标记 Redis::del('product_operations_sequence_added'); }
三、现有代码优化建议
给Model的判断逻辑增加异常容错,避免Redis故障时业务中断:
protected static function boot() { parent::boot(); static::addGlobalScope('order', function (Builder $builder) { $builder->orderBy('product_id', 'asc'); try { if (Redis::exists('product_operations_sequence_added')) { $builder->orderBy('sequence', 'asc'); } } catch (\Exception $e) { // Redis异常时降级不使用sequence排序,不影响主业务 } $builder->orderBy('id', 'asc'); }); }
四、无停机保障说明
- 代码拉取后到迁移完成前,Redis标记不存在,Model不会调用
sequence字段,不会抛出字段不存在的错误,业务正常运行 - MySQL 8.0+、MariaDB 10.3+版本支持即时加列,即使是千万级大表新增字段也不会长时间锁表,业务感知不到中断
- 迁移完成后Redis标记自动生效,新请求会自动按
sequence排序,不需要额外操作
内容的提问来源于stack exchange,提问作者domaci_a_nas
相关产品推荐
相关产品推荐

