开源GitHub官方博客·原文 2026年10月22日

GitHub将 99.99999% 仓库副本迁入Azure,剩余高频仓库改用按引用粒度串行写入

GitHub工程博客披露迁移进展:2025 年 8 月首批仓库副本落地Azure美国中部区域,目前多数仓库五个副本中两个在Azure,Azure承载约一半Git流量;最繁忙的 0.00001% 仓库因约 25ms跨区域往返延迟受制于整仓级写锁,GitHub正把quorum提交范围从整个仓库缩小到单个引用。

AI解读:现有架构下quorum只需多数派即可提交写,但要等所有健康副本响应,最慢副本决定每次写延迟;跨区域往返约 25ms,写入需多次往返。

GitHub的改动是把quorum串行化范围从整仓缩小到单个引用。Git只要求单个引用更新后不再返回旧值,不同引用更新通常互不依赖,因此可并行处理,内部测试中不同引用的写入吞吐提高 3–4 倍。

下一步引入“虚拟写副本”作为object storage在quorum中的成员,写入在对象存储持久化后才确认;读副本可从Azure Blob Storage预热缓存、不加入quorum,按需扩容。

GitHub说明虚拟读副本先在后台与对象存储对账,适合部分读负载而非全部;quorum仍是进一步提升写吞吐的约束,后续方案尚未展开。

文中的 3–4 倍吞吐提升来自GitHub内部使用真实流量的测试,针对不同引用的并发写入,并非对所有仓库或所有负载的公开基准。

GitHub在 3 月(按博客发布时间)的工程博客中说明,过去一年Git流量指数增长,99.99999% 的仓库副本已同时存放在自有数据中心和Azure。首批仓库副本于 2025 年 8 月进入Azure美国中部区域;目前多数仓库五个副本中的两个在Azure,Azure承载约一半Git流量。

剩余 0.00001% 是平台上最繁忙的仓库。GitHub称这部分仓库被一个 25ms的跨区域往返延迟卡住,正通过改变quorum的串行化范围把它们迁入Azure。

为什么最繁忙的仓库还留在自有数据中心

GitHub解释,其Spokes quorum只需多数副本即可提交写,但要等所有健康副本响应(直到超时)才继续,因此最慢的健康副本决定每次写的延迟。每次写还持有整仓级锁直到提交,所以它也决定吞吐上限。

当一个副本位于目标Azure区域,距GitHub自有数据中心约 1,000 英里,每次网络往返约 25ms,而一次写需要多次往返。对于已接近吞吐上限的仓库,每次推送都会进一步落后。

  • 多数仓库有五个副本,用于平衡持久性、可用性和规模;读取通过Spokes的优先路由指向与请求同区域、同可用区的副本。
  • 随着副本逐个迁入Azure,可从Azure服务的流量份额随之增加,直到最后一个副本到达后旧区域不再接收请求。
  • GitHub称迁移节奏受代理(agent)流量增长、数据中心及周边区域电力容量上限和供应链约束推动;其判断是剩余容量只够安全迁移,不够慢速迁移。

改动:把写锁从整个仓库缩到单个引用

GitHub称Git的一致性要求按引用独立适用:服务器接受某个引用更新后,客户端不应再看到更旧的值,只应看到该值或更新值;这对快进、强制推送和删除都成立。但不同引用的更新通常互不依赖。

因此GitHub把quorum的串行化范围从整个仓库改为单个引用。只有争用同一引用的写需要互相等待;开发者和代理推送到各自分支时不再排队。每次写仍承担跨区域延迟,但写不同引用的操作可同时在途。

GitHub称在内部使用真实流量的测试中,对不同引用的写入持续获得 3–4 倍的吞吐提升,且延迟更低;这一数字对应上述并发写入场景,并非对所有仓库或所有负载的公开基准。

读与写分开扩容的下一步

GitHub称多数仓库读远多于写,大约每 1 次写对应 100 到 1,000 次读;目前读写命中同一批副本,争用相同资源,无法独立扩容。

其方案是让Azure Blob Storage成为quorum中的“虚拟副本”:由第一个完全无状态的临时节点代表,只转发写入、不服务读,写入在对象存储持久化后才确认。该虚拟写副本还把不同引用上的事务合并为一次对象存储网络I/O,使繁忙仓库的多次并发写只付一次往返成本。

在此基础上,仓库可按需扩展任意数量的虚拟读副本:每个副本从Azure Blob Storage预热缓存后接收读流量,不加入quorum,以对象存储为事实来源并在后台对账。GitHub称内部分布式压测工具先在虚拟读副本上碰到自身极限。

  • GitHub说明虚拟读副本启动时在后台对账,适合部分读负载;要服务所有读类型,需把对账改为在线进行,只拉取副本上次同步后变化的引用状态和数据。
  • 目前虚拟写副本还负责compaction,读副本继承压缩后的状态。
  • GitHub称quorum仍是写吞吐继续提高的约束;后续设计要让写入只对少量需要排序的数据达成一致,因为Git对象不可变且按内容命名,可无需共识存储。

信息来源

GitHub官方博客原始来源