news 2026/10/21 23:49:01

Laravel Backup 高层架构全解:备份、清理与健康监控三管齐下

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Laravel Backup 高层架构全解:备份、清理与健康监控三管齐下
  • 运维

【免费下载链接】laravel-backup

A package to backup your Laravel app

项目地址:https://gitcode.com/gh_mirrors/la/laravel-backup
点击查看免费下载

本指南基于 laravel-backup 项目官方文档 high-level-overview 展开,系统讲解该包三大核心能力——备份(Taking backups)、清理旧备份(Cleaning up old backups)、监控备份健康(Monitoring the health of all backups),并结合 config/backup.php 与 src 下的源码实现,说明每条命令、每个配置项背后的真实调用逻辑。读完本文,你将掌握backup:run、backup:clean、backup:monitor、backup:list四条命令的完整用法,理解默认清理策略的六条规则,并能根据业务需求自定义健康检查与清理策略。

一、备份(Taking Backups):一条命令打包文件与数据库

备份的本质是产出一个.zip文件,其中包含两部分内容:

  1. 你在配置中指定的目录下的全部文件;
  2. 你所配置数据库的转储(dump)——包内置支持 MySQL、PostgreSQL、SQLite 和 Mongo 四种数据库(见 src/Tasks/Backup/DbDumperFactory.php 与 BackupJob.php 中的数据库转储逻辑)。

生成好的 zip 文件会自动复制到你在配置中指定的任意一个或多个文件系统(Filesystem)上,这些文件系统由 Laravel 自带的 filesystem 配置驱动。

1.1 触发备份的命令

执行一次全新备份,只需运行:

php artisan backup:run

在大多数生产场景下,你都会希望把这个命令加入调度(Schedule),例如在routes/console.php中定时执行。

backup:run还提供了一组实用的运行时选项(可查阅 BackupCommand.php 中的命令签名定义):

选项作用示例
--only-to-disk只备份到指定磁盘,而非全部配置的磁盘php artisan backup:run --only-to-disk=s3
--only-db只备份数据库,跳过文件系统php artisan backup:run --only-db
--db-name只备份指定名称的数据库连接(可多次传入)php artisan backup:run --db-name=mysql
--only-files只备份文件,跳过数据库转储php artisan backup:run --only-files
--filename为备份 zip 指定自定义文件名php artisan backup:run --filename=my-backup.zip
--filename-suffix在默认文件名后追加后缀php artisan backup:run --filename-suffix=-extra
--exclude运行时额外排除目录或文件(可多次使用)php artisan backup:run --exclude=storage/logs --exclude=storage/debugbar
--destination-path覆盖备份的目标存储路径php artisan backup:run --destination-path=custom/path
--disable-notifications本次运行不发送任何通知php artisan backup:run --disable-notifications
--timeout设置备份进程的 PHP 超时时间(秒)php artisan backup:run --timeout=600
--tries配置失败后的重试次数php artisan backup:run --tries=3
--config使用指定的自定义配置文件运行备份php artisan backup:run --config=backup_database

从源码看,这些选项会直接作用于BackupJob对象:例如--only-db对应调用dontBackupFilesystem(),--only-files对应dontBackupDatabases(),--only-to-disk对应onlyBackupTo(),--exclude会调用fileSelection()->excludeFilesFrom()(见 BackupCommand.php)。--timeout则通过set_time_limit()调整 PHP 执行时间上限。

⚠️ 警告(原文档重点强调):请谨慎使用--only-db与--only-files。在监控备份健康时,包不会区分"完整备份"与"只含文件或只含数据库的部分备份"。如果只做了部分备份,一旦出现问题,你可能无法从备份中完整恢复。同时源码也会阻止二者同时使用:guardAgainstInvalidOptions()会抛出InvalidCommand::create('Cannot use only-db and only-files together')(BackupCommand.php)。

1.2 备份内容配置:决定打包哪些文件与数据库

备份内容由config/backup.php中backup.source段决定,该段核心配置如下(完整文件见 config/backup.php):

'backup' => [ // 应用名称,监控备份时用此名称标识本应用 'name' => env('APP_NAME', 'laravel-backup'), 'source' => [ 'files' => [ // 需要纳入备份的目录与文件列表 'include' => [ base_path(), ], // 需要从备份中排除的目录与文件 // 备份过程自身使用的目录会被自动排除 'exclude' => [ base_path('vendor'), base_path('node_modules'), storage_path('framework'), ], // 是否跟随符号链接 'follow_links' => false, // 是否跳过不可读的目录 'ignore_unreadable_directories' => false, // 用于让 zip 内的目录变为相对路径;设为 null 则保留完整绝对路径 'relative_path' => null, ], // 需要备份的数据库连接名称(支持 MySQL、PostgreSQL、SQLite、Mongo) 'databases' => [ env('DB_CONNECTION', 'mysql'), ], ], ],

几个关键点:

  • include默认包含整个项目根目录base_path()。配置文件中还留有一行注释:// storage_path(),提示如果你使用零停机部署(zero downtime deployment)且不跟随符号链接,可能需要额外包含storage_path()。
  • exclude中列出的目录在打包时会被剔除;备份过程自身使用的目录(如备份目标磁盘目录、临时目录)也会被自动排除,具体逻辑见 BackupJob.php 的directoriesUsedByBackupJob()。
  • 数据库转储可针对每个连接自定义:你可以在config/database.php中为某个连接添加dump键,例如:
'mysql' => [ // ... 'dump' => [ 'exclude_tables' => [ 'table_to_exclude_from_backup', 'another_table_to_exclude', ], ], ],

如果 MySQL 服务器上全部使用 InnoDB 表,还可以设置'useSingleTransaction' => true来避免锁表。config/backup.php还提供database_dump_compressor(默认null,可设为Spatie\DbDumper\Compressors\GzipCompressor::class)、database_dump_file_timestamp_format、database_dump_filename_base(database或connection)、database_dump_file_extension等转储细节选项(config/backup.php)。

1.3 目标磁盘配置:决定备份存放在哪里

backup.destination段指定 zip 备份要复制到哪些文件系统:

'destination' => [ // 存放备份的磁盘名称列表 'disks' => [ 'local', ], ],

config('backup.destination.disks')的默认值只包含local一个磁盘。请注意原文档的忠告:如果你只用本地磁盘存放备份,一旦该磁盘崩溃,你将一无所有——"拥有备份"不等于"拥有备份策略"!

因此强烈建议:在config/filesystems.php中额外配置一些磁盘(如 S3、Dropbox 等外部服务),并把它们加入destination.disks。如果你需要给磁盘底层的 Flysystem 驱动传递额外选项,可以在该磁盘配置中加一个backup_options数组:

// config/filesystems.php 'disks' => [ 's3' => [ 'driver' => 's3', // ... 'backup_options' => [ // 在这里添加额外选项 ], ], ],

一个重要的容错设计(源码事实):当向某个文件系统复制 zip 失败时,包仍然会继续尝试向其他所有已配置的文件系统复制(见 BackupJob.php 的copyToBackupDestinations())。只有所有目标都失败时,整个备份才会被判定为失败;destination.continue_on_failure配置项(默认false)控制着这种"部分失败继续执行"的行为。

1.4 备份的文件名与执行流程

默认情况下,zip 文件名格式为<配置中的应用名称>/<Y-m-d-H-i-s>.zip,例如my-app/2026-10-09-03-07-18.zip。文件名的时间戳格式常量定义在 BackupJob.php(FILENAME_FORMAT = 'Y-m-d-H-i-s.zip'),备份名(即"应用名"目录)则通过--destination-path或配置的 name 决定。此外config/backup.php还提供destination.filename_prefix(zip 文件名前缀)、compression_method(默认ZipArchive::CM_DEFAULT)与compression_level(默认 9)等压缩相关配置(config/backup.php)。

从 BackupJob::run() 可以还原完整执行链路:

  1. 在临时目录(storage/app/backup-temp,见 config/backup.php)中准备一个名为temp的临时目录;
  2. createBackupManifest():先转储所有配置的数据库(触发DumpingDatabase事件),再收集需要备份的文件,写入manifest.txt(触发BackupManifestWasCreated事件);
  3. createZipContainingEveryFileInManifest():把清单中的全部文件与数据库转储打成 zip(触发BackupZipWasCreated事件);若配置了verify_backup,还会用ZipArchive重新打开 zip 校验文件数(见verifyBackup(),BackupJob.php);
  4. copyToBackupDestinations():把 zip 复制到所有目标磁盘,成功后触发BackupWasSuccessful事件;
  5. 复制完成后删除临时目录与源 zip。

需要备份的文件越多,zip 越大。请确保磁盘上有足够的空闲空间来生成 zip 文件;源 zip 在被复制到所有目标后会被删除。

1.5 用独立配置跑多个备份域

如果希望按不同范围分别备份 Laravel 应用的各个区域——例如使用不同的调度、数据库连接、文件系统磁盘或清理设置——可以创建自定义的备份配置文件,放在config/目录下:

  • config/backup_database.php
  • config/backup_invoices.php
  • config/backup_uploads.php

然后分别运行备份与清理命令:

php artisan backup:run --config=backup_database php artisan backup:clean --config=backup_database php artisan backup:run --config=backup_invoices php artisan backup:clean --config=backup_invoices php artisan backup:run --config=backup_uploads php artisan backup:clean --config=backup_uploads

从源码看,--config选项会让命令直接从指定配置键重新构建Config对象:Config::fromArray(config($this->option('config')))(BackupCommand.php)。这为调度、保留策略和目标磁盘提供了完全独立的灵活性。

二、清理旧备份(Cleaning Up Old Backups):磁盘空间守门员

随着时间的推移,备份数量与占用的存储空间会不断增长,你终将需要清理旧备份。运行:

php artisan backup:clean

如需使用特定配置执行清理:

php artisan backup:clean --config=backup

先记住一个关键默认行为:无论备份多大、多老,包默认永远不会删除最新的一份备份。

2.1 清理策略配置

config/backup.php中cleanup段决定了哪些备份应当被删除(完整配置见 config/backup.php):

'cleanup' => [ // 用于清理旧备份的策略类。 // 默认策略会保留一定天数内的全部备份; // 该期限过后仅保留每日备份;再往后仅保留每周备份,以此类推。 // 无论怎么配置,默认策略永远不会删除最新的备份。 'strategy' => \Spatie\Backup\Tasks\Cleanup\Strategies\DefaultStrategy::class, 'default_strategy' => [ // 必须保留全部备份的天数 'keep_all_backups_for_days' => 7, // 必须保留每日备份的天数 'keep_daily_backups_for_days' => 16, // 必须保留每周备份的周数 'keep_weekly_backups_for_weeks' => 8, // 必须保留每月备份的月数 'keep_monthly_backups_for_months' => 4, // 必须保留每年备份的年数 'keep_yearly_backups_for_years' => 2, // 清理后若存储仍超出该值(MB),继续删除最旧备份直到达标 // 设为 null 表示不限大小 'delete_oldest_backups_when_using_more_megabytes_than' => 5000, ], ],

配置文件中的注释对这些参数做了更细的补充说明:在keep_all_backups_for_days期满后,每天只保留当天最近的一份备份,同一天内更早的备份会被删除;keep_weekly_backups_for_weeks、keep_monthly_backups_for_months、keep_yearly_backups_for_years同理——如果你每天只创建一次备份,则对应阶段不会再有备份被移除(config/backup.php)。

2.2 默认策略(DefaultStrategy)的六条规则

包提供了一套"有主见"(opinionated)的旧备份判定方法,即DefaultStrategy。它在 DefaultStrategy.php 中实现,工作规则如下:

  • 规则 #1:无论大小与年龄,永不删除最新备份(源码中对应$backups->shift()先把最新备份拿出来保护起来,见 DefaultStrategy.php);
  • 规则 #2:保留keepAllBackupsForDays指定天数内的所有备份;
  • 规则 #3:对早于规则 #2 覆盖范围的所有备份,仅在keepDailyBackupsForDays指定的天数内保留每日备份;
  • 规则 #4:对早于规则 #3 覆盖范围的所有备份,仅在keepMonthlyBackupsForMonths指定的月数内保留每周备份;
  • 规则 #5:仅保留keepYearlyBackupsForYears指定年数内的每年备份(针对早于规则 #4 覆盖范围的所有备份);
  • 规则 #6:如果存储总用量超出deleteOldestBackupsWhenUsingMoreMegabytesThan指定的容量,开始删除最旧备份,直到用量低于该限额(对应 DefaultStrategy.php 中的removeOldBackupsUntilUsingLessThanMaximumStorage())。

策略在实现上把备份按Ymd(日)、YW(周)、Ym(月)、Y(年)四种时间粒度分组,每个分组只保留一份,其余删除(DefaultStrategy.php)。当然,默认配置中的这些数字完全可以按需调整。

2.3 自定义清理策略

如果默认策略无法满足你的需求,可以创建自己的策略:继承抽象类Spatie\Backup\Tasks\Cleanup\CleanupStrategy,只需要实现这一个方法:

use Spatie\Backup\BackupDestination\BackupCollection; public function deleteOldBackups(BackupCollection $backupCollection)

BackupCollection继承自Illuminate\Support\Collection,内部包含按年龄排序的Spatie\Backup\BackupDestination\Backup对象,最新备份排在最前面(见 BackupCollection.php 中newest()、oldest()的实现)。利用集合可以方便地手动删除最旧备份:

// 获取一个 `Spatie\Backup\BackupDestination\Backup` 实例 $backup = $backups->oldestBackup(); // 删除该备份 $backup->delete();

不要忘记在 laravel-backup 配置文件的cleanup.strategy键中填写你自定义策略的完整类名。

三、监控所有备份的健康状况(Monitoring the Health of All Backups)

包还可以为每个安装了它的应用检查备份健康状况。一个备份在以下两种情况下被判定为"不健康(unhealthy)":

  1. 最近一次备份的日期过于久远,已不足以支撑恢复;
  2. 所有备份所需的存储空间不达标/超出限额。

除了监控应用自身的备份,其他应用的备份也可以被一并监控——这正是把它部署为独立监控服务的价值所在。

3.1 推荐的部署方式:独立监控安装

建议单独建立一个 Laravel 安装来做监控,最好放在独立服务器上。这样即使被监控的某个应用宕机,你依然能收到不健康备份的通知。

同时建议:使用监控功能时,备份应存放在中心化的存储磁盘(如 s3)。你仍然可以监控本地磁盘,但那样就必须把监控放进运行备份的那个应用里。

监控安装遵循常规的安装与设置流程,区别在于:不调度backup:run和backup:clean,而是调度监控命令:

// routes/console.php use Illuminate\Support\Facades\Schedule; Schedule::command('backup:monitor')->daily()->at('03:00');

当然,如果你愿意,仍然可以调度backup:run与backup:clean来备份监控应用自身。

3.2 指定监控哪些备份

config/backup.php中monitor_backups段用于指定要监控的应用,以及监控在什么条件下判定某应用的备份不健康:

'monitor_backups' => [ [ 'name' => env('APP_NAME'), 'disks' => ['s3'], 'health_checks' => [ \Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumAgeInDays::class => 1, \Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumStorageInMegabytes::class => 5000, ], ], /* [ 'name' => 'name of the second app', 'disks' => ['s3'], 'health_checks' => [ \Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumAgeInDays::class => 1, \Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumStorageInMegabytes::class => 5000, ], ], */ ],

两个内置健康检查的行为(均有源码佐证):

  • MaximumAgeInDays:如果最新备份比指定天数更旧,检查即失败;若没有备份也会失败。源码实现在 MaximumAgeInDays.php:无备份时判定不健康,否则判断$backup->date()->gt(now()->subDays($this->days))是否为真。不需要该检查时,直接把它从数组中移除即可。
  • MaximumStorageInMegabytes:如果所有备份的总大小超过指定 MB 数,检查即失败。不需要时同样直接移除。

关键约定:监控条目中的name必须与被备份应用的backup.name配置键保持一致(该值默认来自env('APP_NAME'),见 config/backup.php)。从源码看,backup:monitor通过BackupDestinationStatusFactory::createForMonitorConfig()为每个受监控的"应用名 + 磁盘"组合生成状态对象,逐个检查健康与否,不健康时输出错误并触发UnhealthyBackupWasFound事件(见 MonitorCommand.php)。

3.3 查看所有备份的状态

要查看所有受监控目标文件系统的状态,使用:

php artisan backup:list

该命令基于同一份monitor_backups配置生成一个概览表格,列包括:Name(备份名)、Disk(磁盘)、Reachable(可达)、Healthy(健康)、# of backups(备份数)、Newest backup(最新备份)、Used storage(已用存储),并在表格下方单独列出所有不健康目标及其失败检查项(见 ListCommand.php)。执行backup:monitor时,命令行会打印诸如The my-app backups on the s3 disk are considered healthy.或...considered unhealthy!的判定结果。

3.4 获得(不)健康备份的通知

当监控器发现健康或不健康的备份时,你可以收到通知。包内置了HealthyBackupWasFoundNotification与UnhealthyBackupWasFoundNotification,并支持 mail、Slack、Discord、通用 webhook 等通知渠道的配置(见 config/backup.php 与 src/Notifications 目录)。详见 发送通知 一节。

四、围绕三大能力的事件与扩展点

最后从架构角度总结:三大能力(备份、清理、监控)并非孤立模块,它们通过事件机制相互配合,均定义在 src/Events 下,主要包括:

  • 备份生命周期:DumpingDatabase、BackupManifestWasCreated、BackupZipWasCreated、BackupWasSuccessful、BackupHasFailed;
  • 清理结果:CleanupWasSuccessful、CleanupHasFailed;
  • 监控结果:HealthyBackupWasFound、UnhealthyBackupWasFound。

监听器与通知层通过 src/Notifications/EventHandler.php 将这些事件桥接到用户配置的通知渠道,同时包的日志也会写入config/backup.php中log_channel指定的日志渠道(默认使用 Laravel 默认渠道,设false可完全关闭备份日志)。了解这些事件,你就可以在自己的应用里监听它们,做告警、归档、二次校验等自定义扩展。

  • 运维

【免费下载链接】laravel-backup

A package to backup your Laravel app

项目地址:https://gitcode.com/gh_mirrors/la/laravel-backup
点击查看免费下载
上一篇:Foundry `fmt` 源码深读:基于 Solar 的 Solidity 格式化器如何工作(forge fmt 架构、配置与调试)
下一篇:Engauge Digitizer图像数据提取完整实战指南:三步从图表图片到CSV坐标

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 16:04:23

从仓库到Release:系统理解GitHub协作核心概念与工作流

GitHub是什么&#xff1f;很多人会脱口而出&#xff1a;代码托管平台。这个回答不算错&#xff0c;但对一个打算真正用它来协作、来开源项目、来整理个人作品集的人来说&#xff0c;远远不够。我见过不少新人把GitHub当成一个网盘用&#xff1a;上传代码、下载代码、点个Star&a…

作者头像 李华
网站建设 2026/10/21 23:48:56

SpringBoot+Vue+MySQL健身房管理系统:从数据库设计到部署实战

不少做管理系统的朋友看到"可直接运行"四个字就兴奋&#xff0c;但实际拿到项目后&#xff0c;光是环境配置和初始化数据就能耗掉大半天。我做这套健身房管理系统&#xff0c;出发点是给中小型健身房一个开箱即用的信息化工具&#xff0c;后端用SpringBoot&#xff0…

作者头像 李华
网站建设 2026/10/17 23:39:37

从Day1到Day105:面试经典150题刷题复盘与高效计划

从第1天就开始刷这套题的人很多&#xff0c;能坚持到“day105”的并不多。3月6号这天&#xff0c;我刚好卡在100天刚过的节点上&#xff0c;把面试经典150题的进度条拉到接近尾声。回头看这三个月零几天的过程&#xff0c;最大的感受不是“题变简单了”&#xff0c;而是“会做题…

作者头像 李华
网站建设 2026/10/21 16:59:21

TVA具身智能系统简介(12):三层核心架构的定义与层级划分

前沿技术探索&#xff1a;TVA智能体&#xff08;简称TVA&#xff0c;亦称“TVA视觉智能体”或“AI智能体视觉”&#xff09;是依托Transformer架构与“因式智能体”理论构建的通用视觉技术框架。它深度融合深度强化学习&#xff08;DRL&#xff09;、卷积神经网络&#xff08;C…

作者头像 李华