Proxmox Backup Server 维护三剑客:Prune、GC 与 Verify 详解

文章目录

摘要: Proxmox Backup Server(PBS)采用创新的 Chunk 全局去重备份架构,彻底告别传统备份链的脆弱性。它将数据切割为固定大小的 Chunk,通过哈希算法实现跨虚拟机、跨备份的全局去重,显著降低存储占用。每个快照都是独立的完整恢复点,无需依赖备份链,实现快速、可靠的恢复。结合增量备份和压缩技术,PBS 在保证数据完整性的同时,大幅提升备份效率和存储利用率,是企业级虚拟化环境备份的理想解决方案。

延伸阅读

如果想进一步了解 PBS 的其他内容,可以参考以下文章:


PBS 维护操作:Prune、GC 与 Verify

PBS 的 Chunk 全局去重架构带来了显著的存储效率优势,但也引入了新的维护需求:如何清理不再被引用的 Chunk?如何验证备份数据的完整性?这就是 GC(垃圾回收)和 Verify(验证)任务的作用。

一、Prune:管理备份保留策略

Prune(修剪)是 PBS 中用于自动删除过期备份快照 的功能。它根据用户定义的保留策略(如"保留最近7天每日备份,保留最近4周每周备份"),在备份任务运行时自动清理旧的、不再需要的快照索引。Prune 是触发 GC 释放物理空间的关键前置步骤。

例如:

假设 VM 101 有一块磁盘,按每天备份,keep-weekly=2

bash 复制代码
vm/101/
├── 2026-05-10T22:30:00Z/    ← 第1周的备份,保留
│   └── drive-scsi0.img.fidx
│
├── 2026-05-17T22:30:00Z/    ← 第2周的备份,保留
│   └── drive-scsi0.img.fidx
│
├── 2026-05-03T22:30:00Z/    ← 第3周的备份,被 Prune 删除
│   └── drive-scsi0.img.fidx
│
└── 2026-04-26T22:30:00Z/    ← 第4周的备份,被 Prune 删除
    └── drive-scsi0.img.fidx

原理

Prune 操作本身只删除备份快照的索引文件 (如 .fidx, .didx, .img.fidx 等),这些文件存储在快照目录下,体积很小。删除索引意味着该快照从 PBS 的目录视图中消失,无法再用于恢复。

然而,该快照所引用的实际数据块(Chunk)仍然保留在 .chunks/ 目录中,因为其他快照可能还在共享这些 Chunk。这些"失去引用"的 Chunk 就成为了 GC 的清理目标。

简单来说:Prune 负责"逻辑删除"(标记快照过期),GC 负责"物理清理"(回收无引用的数据块)。

配置备份保留策略

Prune 保留策略的配置入口

实际上有两个地方可以配置备份保留策略,侧重点不同:
1. PVE 端(Datacenter → Backup)

在备份任务中直接配置 Prune 策略,备份任务成功完成后立即触发 ,由 PVE 负责执行。策略作用范围是该备份任务覆盖的 VM,适合针对不同 VM 设置差异化的保留策略。
2. PBS 端(Datastore → Prune & GC Jobs)

在 PBS 上独立配置 Prune Job,按照独立的 schedule 定时触发,与备份任务完全解耦。策略作用范围是整个 Datastore 或指定的 VM群组,适合集中统一管理所有 VM 的保留策略。


两者的核心区别:

PVE 端 PBS 端
触发时机 备份任务完成后立即执行 独立 schedule 定时执行
作用范围 单个备份任务覆盖的 VM 整个 Datastore 或指定 VM
管理方式 分散在各个备份任务中 集中在 PBS 统一管理
适用场景 各 VM 保留策略不同 统一策略,集中管理

重要提示 :两端策略若同时配置且不一致,最终生效的是更严格(保留更少)的那一端

可能导致备份被意外删除。建议只在一端配置 Prune 策略,

大多数企业环境推荐统一在 PBS 端管理,PVE 端不设 Prune。

PVE 端(Datacenter → Backup)配置备份保留策略
  1. 在备份任务中配置 :创建或编辑备份任务时,可以在"保留"选项卡中设置 Prune 策略。

  2. 策略说明

    • `keep-last:保持未设置
    • keep-daily=7: 保留最近7天的每日备份。
    • keep-weekly=4:保留最近4周的每周备份(通常指每周日的备份)。
    • keep-monthly=3:保留最近3个月的每月备份(每月第一天的备份)。
    • keep-yearly=1:保留最近1年的每年备份。
  3. 触发时机 :Prune 会在备份任务成功完成后自动执行,根据设定的策略清理该任务历史中的旧快照。

keep-last与keep-daily区别

keep-daily比较宽松,例如,keep-daily=7 的结果:

周五、周四、周三、周二、周一、上周日、上周六 ← 周六空缺

而keep-last更严格,例如,keep-last=7 的结果:强制保留最近 7 个,不管哪天,绝对有 7 个

PBS 端配置备份保留策略

PBS Web UI 中 Datastore → Prune & GC Jobs → Add Prune Job 的配置界面:

** 基本设置**

字段 说明
Datastore test_pbs_backup 这个 Prune Job 作用的 Datastore
Prune Schedule 21:30 每天晚上 21:30 自动执行
Enabled 已勾选 代表当前启用
Namespace Root 作用于根命名空间
Max. Depth Full 递归处理所有子命名空间
Comment 可填写备注,方便在列表中识别用途
Job ID Autogenerate PBS 自动生成唯一 Job ID,也可手动指定

保留策略

保留策略部分,其实与PVE端的设置是一样,不再详细说明

字段 说明
Keep Last 未设置 没有备份强制保留
Keep Hourly 未设置 不按小时粒度保留
Keep Daily 7 最近 7 天内每天保留 1 个
Keep Weekly 4 最近 4 周内每周保留 1 个
Keep Monthly 3 最近 3 个月内每月保留 1 个
Keep Yearly 1 最近 1 年内每年保留 1 个

另外,除了PBS Web UI中配置外,PBS也提供了CLI界面:

bash 复制代码
root@pbs:~#  proxmox-backup-manager help prune 
Usage:

prune-job create <id> --schedule <calendar-event> --store <string> [OPTIONS]
prune-job list [OPTIONS]
prune-job remove <id> [OPTIONS]
prune-job run <id> [OPTIONS]
prune-job show <id> [OPTIONS]
prune-job update <id> [OPTIONS]

以下命令与上方 Web UI 配置等效,通过命令行创建相同策略的 Prune Job:

bash 复制代码
proxmox-backup-manager prune-job create prune-nightly \
  --store test-pbs_backup \
  --schedule "21:30" \
  --keep-daily 7 \
  --keep-weekly 4 \
  --keep-monthly 3 \
  --keep-yearly 1
查看 Prune 后的效果

Prune 完成后,在 Web UI 的"备份"内容中,对应的旧快照会消失。但通过 proxmox-backup-manager garbage-collection status 命令查看,会发现 pending-bytespending-chunks 可能增加了(如果刚运行完 Prune),这些就是等待 GC 安全窗口过后清理的数据。

与 GC 的协同

  1. 顺序:先有 Prune 删除快照(逻辑),后有 GC 回收空间(物理)。
  2. 时间差:Prune 立即生效(快照不可见),但对应的 Chunk 要等到 GC 运行且安全窗口(默认24小时5分钟)过后才会被删除,空间才真正释放。
  3. 监控 :定期检查 GC 状态中的 pending-bytes,可以了解因 Prune 而产生的、即将被释放的空间量。

最佳实践建议

  • 制定清晰的保留策略:根据业务恢复点目标(RPO)和数据重要性制定,平衡存储成本与恢复灵活性。
  • 策略不宜过紧 :避免 keep-daily=1 这样激进的策略,至少保留几天的备份以应对误操作。
  • 理解延迟释放:删除大量历史备份后,不要立即期望看到存储空间大幅下降,需要等待 GC 运行。
  • 结合 GC 调度:将 GC 任务安排在 Prune 可能发生的时间点之后(例如,每日备份任务完成后的几小时)。

二、GC(垃圾回收):释放无用空间

原理

当备份快照被删除(手动删除或按保留策略自动清理)时,PBS 只会删除快照目录下的索引文件(.fidx、.blob 等),而不会立即删除 .chunks/ 目录中对应的 Chunk 文件。这是因为同一个 Chunk 可能被多个备份共享,贸然删除会导致其他备份损坏。

GC 任务会扫描所有存活的备份快照,统计每个 Chunk 的引用计数。引用计数为 0 的 Chunk 表示没有任何备份在使用它,这些 Chunk 会被安全删除,从而释放磁盘空间。

触发方式

  1. 手动触发:通过 Web UI 或命令行手动运行 GC
  2. 自动调度:配置定期 GC 任务(建议每周一次)
  3. 空间阈值触发:当 Datastore 空间使用率达到阈值时自动触发

对存储空间的影响

  • 立即删除快照不会立即释放空间:只有运行 GC 后,空间才会真正释放
  • GC 运行期间性能影响:GC 需要扫描所有 Chunk 的引用关系,会消耗一定的 CPU 和 I/O 资源,建议在业务低峰期运行
  • 空间回收延迟:从删除快照到空间释放,中间存在 GC 运行间隔

命令行操作示例

查看 GC 状态
bash 复制代码
# 查看 Datastore 的 GC 状态
root@PBS01-P:~# proxmox-backup-manager garbage-collection status RS4021XS-02

输出:

复制代码
┌──────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────
│ Name             │ Value                                                                                                
╞══════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════
│ store            │ RS4021XS-02                                                                                      
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ disk-bytes       │ 253565643854   # 当前实际占用磁盘空间(已去重)                                                                                      
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ disk-chunks      │ 184190         #当前磁盘上的 chunk 数量                                                                                             
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ index-data-bytes │ 4880156590080    # 所有索引文件引用的 chunks 总大小(原始逻辑数据量 ≈ 4.54 TiB)                                                                                    
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ index-file-count │ 68             #当前 datastore 中所有索引文件(.fidx 和 .didx)的总数量。                                                                                                  
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ pending-bytes    │ 0   # 待删除(Pending Removal)字节数                                                                                               
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ pending-chunks   │ 0     # 待删除 chunk 数量                                                                                                
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ removed-bad      │ 0     # 本次 GC 删除的损坏 chunk 数                                                                                               
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ removed-bytes    │ 12694985831    # 本次 GC 已释放的字节数                                                                                      
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ removed-chunks   │ 35710   # 本次 GC 已删除的 chunk 数量                                                                                            
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ still-bad        │ 0       # 仍存在的损坏 chunk 数                                                                                             
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ duration         │ 7      # 上次 GC 耗时(秒)                                                                                              
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ last-run-endtime │ 1778983207  # 上次 GC 结束时间(Unix 时间戳)                                                                                         
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ last-run-state   │ OK     # 上次 GC 运行状态                                                                                              
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ next-run         │ 1779588000       # 下次计划运行时间(Unix 时间戳)                                                                                    
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ schedule         │ sun 09:00    # GC 计划任务(每周日 09:00)                                                                                        
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ cache-stats      │ {"hits":979330,"misses":184190}    # GC 缓存命中统计                                                                  
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ upid             │ UPID:PBS01-P:000003A1:00000A9C:00000137:6A092120:garbage_collection:x2dRS4021XS\x2d02:root@pam # 任务唯一 ID
└──────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────
root@PBS01-P:~# 

关键字段解释

字段 含义说明
disk-bytes 当前 datastore 在磁盘上实际占用的空间(去重后)
disk-chunks 当前存储的 chunk 总数
pending-bytes/pending-chunks 已经"不再被任何备份引用",但因为 GC 的安全窗口(grace period,默认 24 小时 5 分钟)尚未到期,所以暂时不能删除的 chunk。
removed-bytes removed-chunks,上次 GC 实际释放的空间和 chunk 数量
last-run-state OK 表示上次 GC 正常完成
next-run 下一次计划执行的时间

为何设置GC 的安全窗口(grace period,默认 24 小时 5 分钟)?

主要基于如下场景:

某些 chunk 原本被某个 backup snapshot 引用。

后来可能:

  • prune 删除了 snapshot
  • 手工删了 backup
  • retention policy 生效
  • namespace 删除
  • VM backup 被删
    这些行为会导致这些对应的chunk 已经没人引用。
    GC 在扫描时会发现:这些chunk处于"unused chunk" 状态
    为避免一下可能的情形,PBS 不会立刻删这些已经没有被引用的chunk,而是设置了一个安全窗口期(grace period)来暂时保留这些已经没有人引用的chunk
  • backup 任务刚完成
  • index 尚未同步
  • datastore metadata 尚未稳定
  • replication 尚未完成

这些 chunk 会在 GC(Garbage Collection)阶段被识别,但不会立即删除。PBS 默认会保留约24 小时 5 分钟的安全保护期(Grace Period),对应 PBS WebUI 中的:

PBS节点--->datastore--->datastore name--->Options--->Tunning Options--->GC Access-Time Cutoff(如下图)

手动运行 GC
复制代码
root@PBS01-P:~# proxmox-backup-manager garbage-collection start RS4021XS-02 

输出:

复制代码
starting garbage collection on store RS4021XS-02
Access time update check successful, proceeding with GC.
Using access time cutoff 1d 5m, minimum access time is 2026-05-23T01:54:37Z
Start GC phase1 (mark used chunks)
marked 1% (1 of 71 index files)
marked 2% (2 of 71 index files)
marked 4% (3 of 71 index files)
marked 5% (4 of 71 index files)
marked 7% (5 of 71 index files)
marked 8% (6 of 71 index files)
marked 9% (7 of 71 index files)
marked 11% (8 of 71 index files)
marked 12% (9 of 71 index files)
marked 14% (10 of 71 index files)
marked 15% (11 of 71 index files)
marked 16% (12 of 71 index files)
marked 18% (13 of 71 index files)
marked 19% (14 of 71 index files)
marked 21% (15 of 71 index files)
marked 22% (16 of 71 index files)
marked 23% (17 of 71 index files)
marked 25% (18 of 71 index files)
marked 26% (19 of 71 index files)
marked 28% (20 of 71 index files)
marked 29% (21 of 71 index files)
marked 30% (22 of 71 index files)
marked 32% (23 of 71 index files)
marked 33% (24 of 71 index files)
marked 35% (25 of 71 index files)
marked 36% (26 of 71 index files)
marked 38% (27 of 71 index files)
marked 39% (28 of 71 index files)
marked 40% (29 of 71 index files)
marked 42% (30 of 71 index files)
marked 43% (31 of 71 index files)
marked 45% (32 of 71 index files)
marked 46% (33 of 71 index files)
marked 47% (34 of 71 index files)
marked 49% (35 of 71 index files)
marked 50% (36 of 71 index files)
marked 52% (37 of 71 index files)
marked 53% (38 of 71 index files)
marked 54% (39 of 71 index files)
marked 56% (40 of 71 index files)
marked 57% (41 of 71 index files)
marked 59% (42 of 71 index files)
marked 60% (43 of 71 index files)
marked 61% (44 of 71 index files)
marked 63% (45 of 71 index files)
marked 64% (46 of 71 index files)
marked 66% (47 of 71 index files)
marked 67% (48 of 71 index files)
marked 69% (49 of 71 index files)
marked 70% (50 of 71 index files)
marked 71% (51 of 71 index files)
marked 73% (52 of 71 index files)
marked 74% (53 of 71 index files)
marked 76% (54 of 71 index files)
marked 77% (55 of 71 index files)
marked 78% (56 of 71 index files)
marked 80% (57 of 71 index files)
marked 81% (58 of 71 index files)
marked 83% (59 of 71 index files)
marked 84% (60 of 71 index files)
marked 85% (61 of 71 index files)
marked 87% (62 of 71 index files)
marked 88% (63 of 71 index files)
marked 90% (64 of 71 index files)
marked 91% (65 of 71 index files)
marked 92% (66 of 71 index files)
marked 94% (67 of 71 index files)
marked 95% (68 of 71 index files)
marked 97% (69 of 71 index files)
marked 98% (70 of 71 index files)
marked 100% (71 of 71 index files)
Start GC phase2 (sweep unused chunks)
processed 1% (2260 chunks)
processed 2% (4564 chunks)
processed 3% (6679 chunks)
processed 4% (8948 chunks)
processed 5% (11246 chunks)
processed 6% (13480 chunks)
processed 7% (15738 chunks)
processed 8% (17980 chunks)
processed 9% (20159 chunks)
processed 10% (22390 chunks)
processed 11% (24659 chunks)
processed 12% (26967 chunks)
processed 13% (29208 chunks)
processed 14% (31612 chunks)
processed 15% (33892 chunks)
processed 16% (36163 chunks)
processed 17% (38455 chunks)
processed 18% (40736 chunks)
processed 19% (43053 chunks)
processed 20% (45367 chunks)
processed 21% (47702 chunks)
processed 22% (49983 chunks)
processed 23% (52337 chunks)
processed 24% (54657 chunks)
processed 25% (56922 chunks)
processed 26% (59150 chunks)
processed 27% (61515 chunks)
processed 28% (63690 chunks)
processed 29% (65963 chunks)
processed 30% (68248 chunks)
processed 31% (70561 chunks)
processed 32% (72901 chunks)
processed 33% (75088 chunks)
processed 34% (77362 chunks)
processed 35% (79669 chunks)
processed 36% (81955 chunks)
processed 37% (84220 chunks)
processed 38% (86495 chunks)
processed 39% (88842 chunks)
processed 40% (91068 chunks)
processed 41% (93386 chunks)
processed 42% (95721 chunks)
processed 43% (98053 chunks)
processed 44% (100338 chunks)
processed 45% (102671 chunks)
processed 46% (105038 chunks)
processed 47% (107294 chunks)
processed 48% (109629 chunks)
processed 49% (111992 chunks)
processed 50% (114259 chunks)
processed 51% (116469 chunks)
processed 52% (118725 chunks)
processed 53% (121020 chunks)
processed 54% (123253 chunks)
processed 55% (125608 chunks)
processed 56% (127923 chunks)
processed 57% (130134 chunks)
processed 58% (132495 chunks)
processed 59% (134720 chunks)
processed 60% (136945 chunks)
processed 61% (139195 chunks)
processed 62% (141388 chunks)
processed 63% (143686 chunks)
processed 64% (145973 chunks)
processed 65% (148264 chunks)
processed 66% (150609 chunks)
processed 67% (152919 chunks)
processed 68% (155222 chunks)
processed 69% (157490 chunks)
processed 70% (159753 chunks)
processed 71% (162045 chunks)
processed 72% (164420 chunks)
processed 73% (166700 chunks)
processed 74% (169052 chunks)
processed 75% (171321 chunks)
processed 76% (173719 chunks)
processed 77% (176054 chunks)
processed 78% (178352 chunks)
processed 79% (180640 chunks)
processed 80% (182953 chunks)
processed 81% (185191 chunks)
processed 82% (187500 chunks)
processed 83% (189803 chunks)
processed 84% (192095 chunks)
processed 85% (194334 chunks)
processed 86% (196608 chunks)
processed 87% (198949 chunks)
processed 88% (201215 chunks)
processed 89% (203496 chunks)
processed 90% (205763 chunks)
processed 91% (208091 chunks)
processed 92% (210407 chunks)
processed 93% (212689 chunks)
processed 94% (215091 chunks)
processed 95% (217449 chunks)
processed 96% (219685 chunks)
processed 97% (221994 chunks)
processed 98% (224203 chunks)
processed 99% (226435 chunks)
Chunk cache: hits 1015866, misses 195014 (hit ratio 83.89%)
Removed garbage: 14.082 GiB
Removed chunks: 33731
Original data usage: 4.619 TiB
On-Disk usage: 244.023 GiB (5.16%)
On-Disk chunks: 195014
Deduplication factor: 19.38
Average chunk size: 1.281 MiB
queued notification (id=2497e0b5-e091-439d-9363-701a0a6a5e3a)
TASK OK

运行GC后,会持续输出处理的进度,处理完成后输出了一组关键统计数据:

bash 复制代码
Chunk cache: hits 1015866, misses 195014 (hit ratio 83.89%)
Removed garbage: 14.082 GiB
Removed chunks:  33731
Original data usage: 4.619 TiB
On-Disk usage:       244.023 GiB (5.16%)
On-Disk chunks:      195014
Deduplication factor: 19.38
Average chunk size:   1.281 MiB
字段 说明
Chunk cache hit ratio 83.89% GC 标记阶段的内存缓存命中率,说明大量 Chunk 被多个快照重复引用
Removed garbage 14.082 GiB 本次 GC 释放的磁盘空间,来自 Prune 删除的过期快照遗留的无引用 Chunk
Removed chunks 33731 本次删除的无引用 Chunk 数量
Original data usage 4.619 TiB 所有快照的原始数据总量(未去重)
On-Disk usage 244.023 GiB (5.16%) 实际占用的磁盘空间,仅为原始数据的 5.16%
On-Disk chunks 195014 当前 Datastore 中存活的 Chunk 总数
Deduplication factor 19.38 去重倍数,原始数据是实际存储空间的 19.38 倍
Average chunk size 1.281 MiB Chunk 平均大小,低于 4MB 目标值,因全零稀疏块拉低了平均值

其中最值得关注的是 Deduplication factor: 19.38------4.619 TiB 的原始数据实际只用了 244GB 存储,这正是 PBS 全局去重在多台 VM 长期备份场景下的真实效果。

查看 GC 历史记录
bash 复制代码
# 查看 .gc-status 文件内容
root@PBS01-P:~# cat /mnt/RS4021XS-02/.gc-status | jq
bash 复制代码
{
  "upid": "UPID:PBS01-P:000003A1:00000A9C:000001CA:6A125BA0:garbage_collection:x2dRS4021XS\\x2d02:root@pam:",
  "index-file-count": 71,
  "index-data-bytes": 5078798827520,
  "disk-bytes": 262018056164,
  "disk-chunks": 195014,
  "removed-bytes": 0,
  "removed-chunks": 0,
  "pending-bytes": 0,
  "pending-chunks": 0,
  "removed-bad": 0,
  "still-bad": 0,
  "cache-stats": {
    "hits": 1015866,
    "misses": 195014
  }
}

字段说明如下:

字段 当前值 说明 当前状态
upid UPID:PBS01-P:... 本次 GC(Garbage Collection)任务的唯一任务 ID 正常
index-file-count 71 当前 datastore 中的 Backup Index 文件数量 正常
index-data-bytes 5078798827520 所有 Backup Snapshot 逻辑引用的数据总量(约 5.08 TB) 逻辑备份容量正常
disk-bytes 262018056164 Chunk 实际占用的物理磁盘空间(约 262 GB) 磁盘利用率非常高
disk-chunks 195014 当前 datastore 中的 chunk 数量 正常
removed-bytes 0 本次 GC 实际删除的数据量 本次无垃圾数据可删除
removed-chunks 0 本次 GC 删除的 chunk 数量 本次无垃圾 Chunk
pending-bytes 0 已失去引用、但仍处于 Grace Period 的数据量 无 Pending Garbage
pending-chunks 0 已失去引用、但尚未实际删除的 chunk 数量 无待删除 Chunk
removed-bad 0 本次 GC 已移除的损坏 chunk 数量 无损坏 Chunk
still-bad 0 GC 完成后仍存在的损坏 chunk 数量 Datastore 健康
cache-stats.hits 1015866 GC Chunk Cache 命中次数 1015866/(1015866+195014 Cache)=83.9%, 命中率优秀
cache-stats.misses 195014 GC Chunk Cache 未命中次数 正常

总的来说:

  • 无损坏的chunk
  • 命中率优秀
  • Dedup Ratio(去重率)极高,约约 19 : 1:
    Dedup Ratio = index-data-bytes ÷ disk-bytes,本例5078798827520 ÷ 262018056164 ≈ 19.38

整体属于一个状态非常健康的 PBS datastore。

GC 调度策略

自定义GC 任务排程

默认,PBS自带一个Garbage Collect jobs:

我们能通过点击图中的"Edit",根据需要调整排程时间

手工运行GC Job:

除了排程运行外,我们也能手工运行GC Job:

复制代码
root@pbs:~# proxmox-backup-manager garbage-collection start test_pbs_backup

输出:

bash 复制代码
starting garbage collection on store test_pbs_backup
Access time update check successful, proceeding with GC.
Using access time cutoff 1d 5m, minimum access time is 2026-05-25T03:19:25Z
Start GC phase1 (mark used chunks)
Start GC phase2 (sweep unused chunks)
processed 73% (0 chunks)
Removed garbage: 0 B
Removed chunks: 0
Original data usage: 0 B
On-Disk chunks: 1
Deduplication factor: 0.00
Average chunk size: 159 B
queued notification (id=ef476961-ad1d-4e7b-8685-87b232ea81d1)
TASK OK
列出GC Job:
bash 复制代码
root@pbs:~# proxmox-backup-manager garbage-collection list

输出

复制代码
root@pbs:~# proxmox-backup-manager garbage-collection list
┌─────────────────┬──────────────────────────┬──────────┬───────────────┬───────────────┬────────────────┬──────────┬──────────────────────────┐
│ store           │ last-run-endtime         │ duration │ removed-bytes │ pending-bytes │ last-run-state │ schedule │ next-run                 │
╞═════════════════╪══════════════════════════╪══════════╪═══════════════╪═══════════════╪════════════════╪══════════╪══════════════════════════╡
│ test_pbs_backup │ Tue May 26 00:01:28 2026 │ 1m 28s   │ 0 B           │ 0 B           │ OK             │ daily    │ Wed May 27 00:00:00 2026 │
└─────────────────┴──────────────────────────┴──────────┴───────────────┴───────────────┴────────────────┴──────────┴──────────────────────────┘

输出说明如下:

字段 说明
store test_pbs_backup 这个 GC 任务所属的 Datastore
last-run-endtime Tue May 26 00:01:28 2026 上次 GC 于今天凌晨 0:01 完成
duration 1m 28s 本次 GC 耗时 1 分 28 秒
removed-bytes 0 B 本次没有清理任何空间,说明没有无引用的孤立 Chunk
pending-bytes 0 B 当前仍无待清理空间,Datastore 状态干净
last-run-state OK 上次 GC 执行成功,无错误
schedule daily 已配置每天自动执行一次 GC
next-run Wed May 27 00:00:00 2026 下次执行时间是明天凌晨 0 点

三、Verify:确保备份完整性

原理

Verify 任务会读取每个备份快照的 .fidx 索引文件,获取该快照引用的所有 Chunk 哈希列表,然后:

  1. 根据哈希值在 .chunks/ 目录中查找对应的 Chunk 文件
  2. 重新计算 Chunk 文件的 SHA-256 哈希
  3. 将计算出的哈希与文件名(即原始哈希)进行比对
  4. 如果哈希不匹配,说明 Chunk 文件已损坏,任务会记录错误

与 index.json.blob 中 csum 的区别

  • csum:验证索引文件(.fidx、.blob)本身的完整性
  • Verify:验证索引文件指向的实际 Chunk 数据的完整性

两者共同构成 PBS 备份完整性的双重保障。

触发方式

  1. 手动触发:通过 Web UI 或命令行手动运行 Verify
  2. 自动调度:配置定期 Verify 任务(建议每月一次)
  3. 恢复前验证:在重要恢复操作前手动运行 Verify

对备份完整性的影响

  • 主动发现损坏:在数据真正丢失前发现损坏的 Chunk
  • 修复机制 :如果 Verify 发现损坏,可以:
    • 从其他 PBS 副本同步(如果配置了同步)
    • 重新备份受影响的 VM
    • 删除损坏的快照(作为最后手段)

命令行操作示例

验证整个datastore
bash 复制代码
# 验证特定 VM 的特定快照
proxmox-backup-manager verify RS4021XS-02 \
  --ignore-verified true \
  --outdated-after 30 \
  --read-threads 2 \
  --verify-threads 4

输出:

bash 复制代码
verify datastore RS4021XS-02
found 19 groups
using 1 read and 4 verify thread(s)
verify group RS4021XS-02:vm/101 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/101/2026-05-23T15:00:05Z (recently verified)
percentage done: 2.63% (0/19 groups, 1/2 snapshots in group #1)
SKIPPED: verify RS4021XS-02:vm/101/2026-05-17T15:30:08Z (recently verified)
percentage done: 5.26% (1/19 groups)
verify group RS4021XS-02:vm/102 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/102/2026-05-23T15:00:12Z (recently verified)
percentage done: 7.89% (1/19 groups, 1/2 snapshots in group #2)
SKIPPED: verify RS4021XS-02:vm/102/2026-05-17T15:30:14Z (recently verified)
percentage done: 10.53% (2/19 groups)
verify group RS4021XS-02:vm/103 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/103/2026-05-23T16:59:06Z (recently verified)
percentage done: 13.16% (2/19 groups, 1/2 snapshots in group #3)
SKIPPED: verify RS4021XS-02:vm/103/2026-05-16T19:00:02Z (recently verified)
percentage done: 15.79% (3/19 groups)
verify group RS4021XS-02:vm/104 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/104/2026-05-23T15:00:18Z (recently verified)
percentage done: 18.42% (3/19 groups, 1/2 snapshots in group #4)
SKIPPED: verify RS4021XS-02:vm/104/2026-05-17T15:30:20Z (recently verified)
percentage done: 21.05% (4/19 groups)
verify group RS4021XS-02:vm/105 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/105/2026-05-23T15:01:35Z (recently verified)
percentage done: 23.68% (4/19 groups, 1/2 snapshots in group #5)
SKIPPED: verify RS4021XS-02:vm/105/2026-05-17T15:30:47Z (recently verified)
percentage done: 26.32% (5/19 groups)
verify group RS4021XS-02:vm/106 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/106/2026-05-23T15:01:41Z (recently verified)
percentage done: 28.95% (5/19 groups, 1/2 snapshots in group #6)
SKIPPED: verify RS4021XS-02:vm/106/2026-05-17T15:30:53Z (recently verified)
percentage done: 31.58% (6/19 groups)
verify group RS4021XS-02:vm/107 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/107/2026-05-23T17:00:41Z (recently verified)
percentage done: 34.21% (6/19 groups, 1/2 snapshots in group #7)
SKIPPED: verify RS4021XS-02:vm/107/2026-05-16T19:00:42Z (recently verified)
percentage done: 36.84% (7/19 groups)
verify group RS4021XS-02:vm/108 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/108/2026-05-23T17:00:49Z (recently verified)
percentage done: 39.47% (7/19 groups, 1/2 snapshots in group #8)
SKIPPED: verify RS4021XS-02:vm/108/2026-05-16T19:00:48Z (recently verified)
percentage done: 42.11% (8/19 groups)
verify group RS4021XS-02:vm/109 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/109/2026-05-23T17:01:02Z (recently verified)
percentage done: 44.74% (8/19 groups, 1/2 snapshots in group #9)
SKIPPED: verify RS4021XS-02:vm/109/2026-05-16T19:00:56Z (recently verified)
percentage done: 47.37% (9/19 groups)
verify group RS4021XS-02:vm/110 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/110/2026-05-23T17:01:08Z (recently verified)
percentage done: 50.00% (9/19 groups, 1/2 snapshots in group #10)
SKIPPED: verify RS4021XS-02:vm/110/2026-05-16T19:01:02Z (recently verified)
percentage done: 52.63% (10/19 groups)
verify group RS4021XS-02:vm/111 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/111/2026-05-23T17:01:15Z (recently verified)
percentage done: 55.26% (10/19 groups, 1/2 snapshots in group #11)
SKIPPED: verify RS4021XS-02:vm/111/2026-05-16T19:01:09Z (recently verified)
percentage done: 57.89% (11/19 groups)
verify group RS4021XS-02:vm/112 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/112/2026-05-23T15:01:49Z (recently verified)
percentage done: 60.53% (11/19 groups, 1/2 snapshots in group #12)
SKIPPED: verify RS4021XS-02:vm/112/2026-05-17T15:31:00Z (recently verified)
percentage done: 63.16% (12/19 groups)
verify group RS4021XS-02:vm/113 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/113/2026-05-23T15:02:04Z (recently verified)
percentage done: 65.79% (12/19 groups, 1/2 snapshots in group #13)
SKIPPED: verify RS4021XS-02:vm/113/2026-05-17T15:31:07Z (recently verified)
percentage done: 68.42% (13/19 groups)
verify group RS4021XS-02:vm/114 (1 snapshots)
SKIPPED: verify RS4021XS-02:vm/114/2026-05-07T07:25:56Z (recently verified)
percentage done: 73.68% (14/19 groups)
verify group RS4021XS-02:vm/115 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/115/2026-05-23T17:01:32Z (recently verified)
percentage done: 76.32% (14/19 groups, 1/2 snapshots in group #15)
SKIPPED: verify RS4021XS-02:vm/115/2026-05-16T19:01:19Z (recently verified)
percentage done: 78.95% (15/19 groups)
verify group RS4021XS-02:vm/116 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/116/2026-05-23T17:02:02Z (recently verified)
percentage done: 81.58% (15/19 groups, 1/2 snapshots in group #16)
SKIPPED: verify RS4021XS-02:vm/116/2026-05-16T19:01:27Z (recently verified)
percentage done: 84.21% (16/19 groups)
verify group RS4021XS-02:vm/117 (1 snapshots)
SKIPPED: verify RS4021XS-02:vm/117/2026-05-08T14:00:07Z (recently verified)
percentage done: 89.47% (17/19 groups)
verify group RS4021XS-02:vm/120 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/120/2026-05-23T15:02:15Z (recently verified)
percentage done: 92.11% (17/19 groups, 1/2 snapshots in group #18)
SKIPPED: verify RS4021XS-02:vm/120/2026-05-17T15:31:13Z (recently verified)
percentage done: 94.74% (18/19 groups)
verify group RS4021XS-02:vm/122 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/122/2026-05-23T15:02:37Z (recently verified)
percentage done: 97.37% (18/19 groups, 1/2 snapshots in group #19)
SKIPPED: verify RS4021XS-02:vm/122/2026-05-17T15:31:22Z (recently verified)
percentage done: 100.00% (19/19 groups)
TASK OK

重点其实看末尾出现:

bash 复制代码
TASK OK

表示:

Verify 完成

没发现损坏 Chunk

Backup 完整性正常

参数说明:

参数 默认值 说明
<store> 必填 指定要验证的 Datastore 名称,例如 RS4021XS-02
--ignore-verified true 跳过已验证且未过期的快照,避免重复验证浪费时间,配合 --outdated-after 使用
--outdated-after 如果一个快照已经验证过,就跳过它,不重复验证。而 Re-Verify After: 30 days,一次验证完成后,经过多少天就视为"已过期",是对这个跳过规则的补充限制:即使已经验证过,但如果距离上次验证已经超过 30 天,就被视为"异过期",重新验证一次。这个设计的目的是在性能和安全之间取得平衡------不需要每次都对所有快照全量验证(耗时很长),但也不允许一个快照永远只验证一次就再也不管,30 天后强制复查,确保数据在存储过程中没有发生静默损坏。
--read-threads 1 读取 Chunk 的线程数,范围 1-32。适当调大可提升验证速度,但会增加磁盘 I/O
--verify-threads 4 验证 Chunk 哈希的线程数,范围 1-32,CPU 密集型操作,调大可加快校验速度
--output-format text 输出格式,可选 textjsonjson-prettyjson 格式适合脚本解析结果

也能透过webui进行验证:

验证单个VM

进入PBS Node--->Datastore--->Datastore Name--->Contents,选中目标VM后右键选择Verify

输出:

Verify 调度策略

自定义Verify Job

创建每月第一天的晚上21 点运行的 Verify 任务

bash 复制代码
proxmox-backup-manager verify-job create verify-nightly \
  --store test_pbs_backup \
  --schedule "21:00" \
  --ignore-verified true \
  --outdated-after 30 \
  --read-threads 2 \
  --verify-threads 4 \
  --comment "每晚9点定期验证备份完整性"

参数说明:

参数 说明
verify-nightly Job ID 这个 Verify Job 的唯一识别名称
--store RS4021XS-02 要验证的 Datastore
--schedule 21:00 每晚 9 点执行
--ignore-verified true 跳过已验证且未过期的快照
--outdated-after 30 超过 30 天未验证的快照强制重新验证
--read-threads 2 读取 Chunk 的线程数
--verify-threads 4 验证哈希的线程数
--comment 备注 方便在 Web UI 识别这个 Job 的用途

列出Verify Job:

bash 复制代码
root@PBS01-P:~# proxmox-backup-manager verify-job list

输出

bash 复制代码
root@pbs:~#  proxmox-backup-manager verify-job list
┌────────────────┬─────────────────┬──────────┬─────────────────┬────────────────┬───────────────────────────┐
│ id             │ store           │ schedule │ ignore-verified │ outdated-after │ comment                   │
╞════════════════╪═════════════════╪══════════╪═════════════════╪════════════════╪═══════════════════════════╡
│ verify-nightly │ test_pbs_backup │ 21:00    │               1 │             30 │ 每晚9点定期验证备份完整性 │
└────────────────┴─────────────────┴──────────┴─────────────────┴────────────────┴───────────────────────────┘

其他更多操作,可查看命令行帮助:

bash 复制代码
root@pbs:~#  proxmox-backup-manager help verify-job 
Usage:

verify-job create <id> --store <string> [OPTIONS]
verify-job list [OPTIONS]
verify-job remove <id> [OPTIONS]
verify-job run <id> [OPTIONS]
verify-job show <id> [OPTIONS]
verify-job update <id> [OPTIONS]

也能透过webui,更直观方便:

四、监控与告警

  1. 监控 Prune 运行结果 :定期检查 Prune Job 的执行记录,确认过期快照已按策略清理,
    关注是否有快照数量异常增长的情况。可通过以下命令查看:
bash 复制代码
   proxmox-backup-manager prune-job list
  1. 监控 GC 运行结果 :检查 .gc-status 文件中的 last-run 时间和释放空间大小,
    确认 GC 在 Prune 之后正常运行并回收了预期的磁盘空间:
bash 复制代码
   proxmox-backup-manager garbage-collection list
  1. 监控 Verify 结果 :定期检查验证日志,关注 ERRORWARNING 级别的消息,
    任何 Chunk 哈希不一致都应立即排查底层存储是否发生静默数据损坏:
bash 复制代码
   proxmox-backup-manager verify-job list
  1. 设置空间告警 :当 Datastore 使用率超过 80% 时触发告警,优先检查 Prune 策略是否

    过于宽松,或 GC 是否长时间未运行导致孤儿 Chunk 堆积。

  2. 验证频率 :生产环境建议每月全量验证一次,重要备份在恢复前额外验证。

    Prune 策略建议在 PVE 端和 PBS 端统一配置,避免两端策略冲突导致备份被意外删除。


五、实际案例:GC 运行效果

查看 GC 运行前后的空间变化:

bash 复制代码
# GC 运行前
root@PBS01-P:~# df -h /mnt/RS4021XS-02/
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1       10T   8.2T  1.8T  83% /mnt/RS4021XS-02

# 运行 GC
root@PBS01-P:~# proxmox-backup-manager garbage-collection run RS4021XS-02 --verbose
...
[INFO] removed 12457 unused chunks, freed 48.7 GiB
[INFO] garbage collection finished successfully

# GC 运行后
root@PBS01-P:~# df -h /mnt/RS4021XS-02/
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1       10T   8.1T  1.9T  82% /mnt/RS4021XS-02

在这个例子中,GC 清理了 12457 个不再被引用的 Chunk,释放了 48.7GB 的存储空间。


六、总结

Prune、GC 和 Verify 是 PBS 日常维护中不可或缺的三个核心操作,三者分工明确,缺一不可:

  • Prune 负责按照保留策略清理过期快照,删除不再需要的 .fidx 索引文件,决定哪些备份时间点需要保留,哪些可以淘汰。Prune 不会立即释放磁盘空间,需配合 GC 使用。
  • GC 负责清理被 Prune 删除后无人引用的"孤儿"Chunk,真正回收磁盘空间,确保去重机制不会导致空间持续增长。
  • Verify 负责主动校验备份数据的完整性,逐一验证 Chunk 的哈希是否与文件名一致,确保在需要恢复时数据真实可用,而不是等到恢复时才发现数据已损坏。

三者的执行顺序也有依赖关系:Prune 先行,GC 紧随,Verify 定期执行。Prune 不运行,GC 就没有可回收的 Chunk;GC 不运行,Prune 后的磁盘空间就无法释放;Verify 不运行,备份数据的完整性就得不到主动保障。

合理配置三项任务的调度策略,并建立相应的监控告警机制,是保障 PBS 备份系统长期稳定运行的关键。虽然 PBS 的架构设计大大简化了备份管理,但定期的维护操作仍然是保证数据安全的重要环节。

相关推荐
云飞云共享云桌面18 小时前
传统工作站 vs 云飞云共享云桌面:制造业设计云桌面选型深度对比
运维·服务器·前端·网络·3d·架构·制造
Maynor99621 小时前
我用 Codex 给自己的网站上线了一个智能体客服:从 Dify 到服务器部署,全程实战复盘
运维·服务器
java_cj1 天前
深入kubectl create源码:从YAML到Pod的完整链路拆解
运维·云原生·容器·kubernetes
深圳恒讯1 天前
越南服务器BGP多线和单线有什么区别?
运维·服务器
志栋智能1 天前
超自动化运维如何提升安全合规水平?
运维·安全·自动化
A_humble_scholar1 天前
Linux(九) 进程管理完全指南:从入门到实战
linux·运维·chrome
江华森1 天前
Linux 操作命令完全指南
linux·运维
源图客1 天前
【AI向量数据库】Weaviate介绍与部署
运维·docker·容器
用什么都重名1 天前
Git分支合并与远程服务器同步实战:保留关键配置文件
运维·服务器·git
C++ 老炮儿的技术栈1 天前
Ubuntu root账号自动登陆
linux·运维·服务器·c语言·c++·ubuntu·visual studio