查看原文
其他

GitHub 数据库 15 年进化史:幕后英雄如何成就 Copilot 传奇

天舟 Bytebase 2024-02-05


自 2008 年成立以来,GitHub 的数据库系统经历了多次重大的演变,以适应不断增长的用户基础和不断变化的技术需求。GitHub 一直使用 MySQL 数据库,其中保存了除了 git 代码仓库以外的其他所有元数据,诸如用户,issue,PR, Gist 这些。在 2023 年结束之际,我们就一起来回顾一下这 15 年来 GitHub 数据库的演进之路。

起步 (2007 ~ 2009)

第 1 个仓库诞生于 2007 年的 10 月 29 日,而第 1000 个则是在来年的 2 月 25 日。
GitHub 是一个 Rails 应用,这个主应用在内部叫做 Monolith,称呼也一直沿用至今。GitHub 一开始是跑在 Engine Yard 上的,从 Logo 上也可以看出 Engine Yard 和 Rails 社区的渊源。
不过因为 GitHub 的增长过快,以及商业化路线和 Engine Yard 初衷有偏离,所以 GitHub 很快又迁移到了 Rackspace。
Rackspace 是一个如今已经陌生的名字,但在 2009 年还是云服务的首选,上面是 GitHub 当时的评估。
这个阶段的数据库架构也比较简单,MySQL(这个时间点应该是 5.0 或者 5.1),一主一备,通过 DRBD 同步。

确定领域模型 (2010)

GitHub 在 2010 年,经过 2 年不断的打磨,终于发布了大家如今熟悉的 PR 工作流。
也是在同一时期,引入了 Organization 这个概念。
所以从领域模型来看,GitHub 从 2010 后就再也没有变过。

迁移数据中心以及第一次拆库 (2013)

GitHub 把数据库迁移到了新的数据中心,升级了存储和网络。同时也把历史数据拆分到了单独的集群。立竿见影,页面加载速度大幅提升。

读写分离,大表变更,高可用 HA (2015 ~ 2019)

这个阶段围绕 MySQL 打造了一系列中间件。
引入 ProxySQL,做读写分离。
不满足已有的基于 trigger 的方案,GitHub 自研了 triggerless 的 gh-ost 来做大表无锁变更。如今被 GitHub 开源的 gh-ost 也是业界最主流的 MySQL 大表变更方案。
再结合自研的 Orchestrator + Consul + HAProxy 做了高可用 HA 方案。
虽然没有找到相关资料,但这个阶段 GitHub 至少把 MySQL 升级到了 5.6,因为 Orchestrator 需要依赖 5.6 引入的 GTID (global transaction identifier)。
另外在 2018 年,Microsoft 以 75 亿美元收购了 GitHub。
GitHub 联创/CEO Chris Wanstrath, Microsoft CEO Satya Nadella, 收购后 GitHub 第一任 CEO Nat Friedman

变更自动化 (2020)

随着 GitHub 模块越来越多,处理数据库变更成为了数据库团队的瓶颈。于是他们通过 GitHub PR + GitHub Actions + skeema 做了一套自动化的方案,这套方案的亮点在于:
  1. Schema as code,用对待代码变更的方式对待数据库变更。开发只要定义最终期望的 schema,比如 CREATE TABLE 语句,然后通过 skeema 来自动计算出需要 ALTER TABLE 语句。

  2. 基于 GitHub 本身的 PR, Actions 能力构建工作流。

引入微服务,进一步拆库 (2019 ~ 2021)

这时 Rails + MySQL 主集群 mysql1 的架构支撑了 GitHub 12 年的发展。
同时在外部用户和内部组织增长的背景下,GitHub 开始引入微服务,对系统进行模块化。
数据库层面做了几个事情,定义好服务和数据的归属关系,要获取归属于其他服务的数据,只能通过 API 的方式。
确立系统边界,用于做垂直分片 (Vertical Partitioning)。
同时也对一些表比如用户表引入水平分片 (Horizontal Sharding),提升隔离性,降低爆炸半径 (Blast Radius)。
也是在这个过程中,GitHub 引入了基于 MySQL 的分布式数据库集群方案 Vitess。
2019 项目启动时,单 mysql1 主集群承担 950,000 QPS。到 2021 年,拆分完的多个集群共同承担 1,200,000 QPS。同时每一个数据库节点的负载则下降了一半。
也是在 2021 年,GitHub 发布了 Copilot,开启了这一轮 AI 革命的序幕。

成长的烦恼 (2022)

即使对 mysql1 主集群做了拆分,但依然跟不上 GitHub 的高速发展。比如在 2022 年 3 月份,就接连发生了 4 次数据库导致的故障,官方也不得不出面解释。故障频发一方面是负载增大,另一方面是为了应对负载,开始继续对 mysql1 做拆库。但在这个过程中,因为配置失误,又导致了故障。开着飞机换引擎风险是高,但 GitHub 也确实没有了当年可以停机升级数据库的奢侈了。

升级到 8.0 (2023)

随着 MySQL 5.7 EOL 的临近,GitHub 开始做 5.7 到 8.0 的迁移。
这时的 GitHub 已经达到了 1200+ 的 MySQL 节点。而 QPS 达到了 5,500,000,相比 21 年披露的 1,200,000,又翻了好几倍,足见 GitHub 发展的迅猛!
鉴于 GitHub 的体量,以及 5.7 到 8.0 本身是一场大版本升级,所以 GitHub 设计了相当复杂的升级方案,主要是应对回滚。
引入微服务后,GitHub 应用有了不同的技术栈,但整体上 GitHub 还是以 Rails 为主,都用 Trilogy 连接数据库。这点保障了升级时的前后兼容性。
升级过程也吃到了之前拆库的红利。
不过另一方面之前引入的 Vitess 也造成了一些麻烦。

整体回顾

最后再来看一下当前 GitHub 的整体架构,通过网上拼凑的信息,大体如下
GitHub 拆分了一些微服务,但核心仍然是 Monolith 这个 Rails 应用。最核心的数据库依然是 mysql1 的 MySQL 集群,由一主多备组成。有些业务域,垂直拆分出了单独的数据库集群,同时也引入 Vitess 做水平拆分。此外还有用于缓存的 Redis 和用于搜索的 ElasticSearch。
GitHub 的数据库演进分三条线:
  1. 基础设施。迁移数据中心,升级 MySQL 版本。

  2. 应用架构。读写分离,高可用,分库。

  3. 数据库变更流程。大表变更,变更自动化。

GitHub 在早年分享时就讲过自己的数据库故事挺无趣的,这么多年了,应用架构和数据模型都没怎么变,15 年前的 MySQL 集群也依然是今天的核心。

以上就是 GitHub 数据库 15 年的进化之路。最后再讲一个插曲
GitHub 联创 Chris 提到当年曾差点把 GitHub 从 MySQL 转到 Postgres,临门一脚卡在了重写一条 GROUP BY 语句上。
不过无论是选择 MySQL 还是 PG,GitHub 多半都能达到今天的高度。总之,我们应该采用无聊的技术去构建创新的产品,而不是倒过来。

其它 GitHub 相关文章

继续滑动看下一个

GitHub 数据库 15 年进化史:幕后英雄如何成就 Copilot 传奇

天舟 Bytebase
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存