Help us learn about your current experience with the documentation. Take the survey.

仓库维护

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

GitLab 支持并自动化 Git 仓库中的维护任务,以确保它们能够以最高效的方式提供服务。维护任务包括:

  • 压缩 Git 对象和修订版本。
  • 删除不可达对象。
  • 删除锁文件等陈旧数据。
  • 维护提升性能的数据结构。
  • 更新对象池以改进分支间的对象去重。

不要手动执行 Git 命令来执行由 GitLab 控制的 Git 仓库的维护操作。这样做可能会导致仓库损坏和数据丢失。

维护策略

Gitaly 可以通过两种方式在 Git 仓库中执行维护任务:

  • 主动维护 执行特定的维护任务,不依赖于仓库的状态。
  • 启发式维护 基于一组启发式规则执行维护任务,根据仓库状态确定需要执行哪些维护任务。

主动维护

“主动"维护策略独立于仓库状态执行仓库中的维护任务。这是由手动触发和基于推送的触发器使用的默认策略。

主动维护策略由 GitLab 应用程序控制。根据触发维护作业运行的触发器,GitLab 会要求 Gitaly 执行特定的维护任务。即使仓库处于优化状态,Gitaly 也会执行这些任务。因此,在大型仓库中,这种策略可能效率低下,因为执行维护任务可能很慢。

启发式维护

启发式(或"机会性”)维护策略分析仓库状态,仅在发现一个或多个数据结构优化不足时才执行维护任务。这是由计划维护使用的策略。

启发式维护使用以下信息来决定需要运行的任务:

  • 松散和陈旧对象的数量。
  • 包含已压缩对象的包文件数量。
  • 松散引用的数量。
  • 提交图的存在性。

是否需要优化任何分析的数据结构的决定基于仓库的大小:

  • 对象的总大小越大,对象重新打包的频率越高。
  • 引用总数越多,引用重新打包的频率越低。

Gitaly 这样做是为了抵消优化这些数据结构所需时间随其增大而增加的事实。在接收大量流量的大型单体仓库中,避免过于频繁地优化它们尤为重要。

您可以更改 Gitaly 被要求优化仓库的频率。

  1. 在左侧边栏底部,选择 Admin
  2. 选择 Settings > Repository
  3. 展开 Repository maintenance
  4. Housekeeping 部分,配置维护选项。
  5. 选择 Save changes
  • Enable automatic repository housekeeping:定期要求 Gitaly 运行仓库优化。如果您长时间禁用此设置,GitLab 服务器上的 Git 仓库访问会变慢,并且您的仓库会使用更多磁盘空间。
  • Optimize repository period:Git 推送次数,之后 Gitaly 会被要求优化仓库。

运行维护任务

GitLab 通过不同方式运行维护任务:

  • 项目管理员可以手动触发仓库维护任务。
  • GitLab 可以在多次 Git 推送后自动安排维护任务。
  • GitLab 可以安排一个作业,在可配置的时间段内为所有仓库运行维护任务。

手动触发

仓库管理员可以手动触发仓库中的维护任务。通常不需要这样做,因为 GitLab 知道自动运行维护任务。手动触发在以下情况下可能有用:

  • 已知某个仓库需要维护。
  • 已禁用基于推送的维护任务自动调度。

要手动触发维护任务:

  1. 在左侧边栏,选择 Search or go to 并找到您的项目。
  2. 选择 Settings > General
  3. 展开 Advanced
  4. 选择 Run housekeeping

这将为项目仓库启动一个异步后台工作进程。后台工作进程要求 Gitaly 执行多项优化。

维护任务还会在每 200 次推送时删除未引用的 LFS 文件,为您的项目释放存储空间。

清理不可达对象

不可达对象作为计划维护的一部分被清理。但是,您也可以触发手动清理。触发维护任务时,会以两周的宽限期清理不可达对象。当您手动触发清理不可达对象时,宽限期将缩短为 30 分钟。

清理不可达对象不能保证删除泄露的密钥和其他敏感信息。有关如何删除已提交但未推送的密钥的信息,请参阅从提交中删除密钥教程。 此外,您可以单独删除 blob。请参阅该文档了解执行此操作的潜在后果。

如果并发进程(如 git push)已创建对象但尚未创建对该对象的引用,则在删除对象后添加对该对象的引用时,您的仓库可能会损坏。宽限期旨在降低此类竞争条件的可能性。 例如,如果通过有时非常慢的连接频繁推送许多大对象,那么清理不可达对象带来的风险远高于企业环境,在企业环境中,项目只能通过高性能的公司内部网络访问。使用此选项时请考虑项目使用情况,并选择一个安静的时间段。

要手动触发清理不可达对象:

  1. 在左侧边栏,选择 Search or go to 并找到您的项目。
  2. 选择 Settings > General
  3. 展开 Advanced
  4. 选择 Run housekeeping
  5. 等待 30 分钟让操作完成。
  6. 返回到您选择 Run housekeeping 的页面,然后选择 Prune unreachable objects

计划维护

  • Offering: GitLab Self-Managed

虽然 GitLab 会根据推送次数自动执行维护任务,但它不会维护完全没有收到任何推送的仓库。因此,休眠仓库或仅接收读取请求的仓库可能无法从仓库维护策略的改进中受益。

管理员可以启用一个后台作业,以可自定义的间隔对所有仓库执行维护,以解决此问题。该后台作业以随机顺序处理 Gitaly 节点托管的所有仓库,并主动对其执行维护任务。如果处理时间超过配置的间隔,Gitaly 节点将停止处理仓库。

配置计划维护

Git 仓库的后台维护在 Gitaly 中配置。默认情况下,Gitaly 每天中午 12:00 执行后台仓库维护,持续 10 分钟。

您可以在 Gitaly 配置中更改此默认设置。

对于具有 Gitaly 集群(Praefect)的环境,计划维护的开始时间可以在 Gitaly 节点之间错开,以便计划维护不会同时在多个节点上运行。

如果计划维护运行达到指定的 duration,正在运行的任务将被优雅地取消。在后续的计划维护运行中,Gitaly 会随机打乱仓库列表进行处理。

以下代码片段为 default 存储启用每天 23:00 开始、持续 1 小时的后台仓库维护:

[daily_maintenance]
start_hour = 23
start_minute = 00
duration = 1h
storages = ["default"]

使用以下代码片段完全禁用后台仓库维护:

[daily_maintenance]
disabled = true
gitaly['configuration'] = {
  daily_maintenance: {
    disabled: false,
    start_hour: 23,
    start_minute: 00,
    duration: '1h',
    storages: ['default'],
  },
}

使用以下代码片段完全禁用后台仓库维护:

gitaly['configuration'] = {
  daily_maintenance: {
    disabled: true,
  },
}

当执行计划维护时,您可以在您的 Gitaly 日志 中看到以下条目:

# 当计划维护开始时
{"level":"info","msg":"maintenance: daily scheduled","pid":197260,"scheduled":"2023-09-27T13:10:00+13:00","time":"2023-09-27T00:08:31.624Z"}

# 当计划维护完成时
{"actual_duration":321181874818,"error":null,"level":"info","max_duration":"1h0m0s","msg":"maintenance: daily completed","pid":197260,"time":"2023-09-27T00:15:21.182Z"}

actual_duration(以纳秒为单位)表示计划维护执行所花费的时间。在前面的示例中,计划维护在刚刚超过 5 分钟的时间内完成。

对象池仓库

  • Offering: GitLab Self-Managed

对象池仓库被 GitLab 用于去重仓库分支中的对象。在创建第一个分支时,我们:

  1. 创建一个对象池仓库,其中包含即将被分支的仓库的所有对象。
  2. 使用 Git 的 alternates 机制将仓库链接到这个新的对象池。
  3. 重新打包仓库,使其使用对象池中的对象。因此它可以删除自己的对象副本。

该仓库的任何分支现在都可以链接到对象池,因此只需要保留与主仓库不同的对象。

GitLab 需要在对象池中执行特殊的维护操作:

  • Gitaly 永远不能从对象池中删除不可达对象,因为它们可能被连接到它的任何分支使用。
  • 由于同样的原因,Gitaly 必须保持所有对象可达。因此,对象池维护对不可达的"悬空"对象的引用,以便它们永远不会被删除。
  • GitLab 必须定期更新对象池,以拉入主仓库中添加的新对象。否则,对象池在去重对象时会变得越来越低效。

这些维护操作由专门的 FetchIntoObjectPool RPC 执行,该 RPC 处理所有这些特殊任务,同时执行我们为标准 Git 仓库执行的常规维护任务。

每当主成员被垃圾回收时,对象池都会自动优化。因此,可以使用该项目中相同的 Git GC 周期来配置频率。

如果您需要从 Rails 控制台 手动调用 RPC,您可以调用 project.pool_repository.object_pool.fetch。这是一个可能长时间运行的任务,但 Gitaly 大约 8 小时后会超时。