前两天 GitHub 的博客上发布了一篇题为「Partitioning GitHub’s relational databases to handle scale」[1] 讲述他们如何拆分自己的数据库。相关内容在 Hacker News[2] 上也引起了大家的关注。
拆分前的 GitHub
一直以来 GitHub 上几乎所有的元数据信息(不包括存放的代码仓库本身)都是存在一个叫 mysql1 的数据库集群上,这个集群由一主多备组成。所以本质上 GitHub 一直是一个单体 MySQL 支撑的应用,一直到 2019,为了应对增长以及提高可用性,GitHub 决定对数据库进行拆分。
拆分的方法
一提到数据库拆分,通常大家想到的会是分库分表水平拆分的 Sharding 方案,无论是分布式中间件,还是现在的主流分布式数据库优先支持的也都是 Sharding 方案。不过 GitHub 选的是另一条路,按照业务逻辑进行垂直拆分,比如把存取 gist 相关信息的表 gists, gist_comments,starred_gists 拆到单独的一个数据库里(虽然文章最后提到 GitHub 也使用了 Sharding 的方案,但从当前这篇分享的内容看,目前的拆分还是以垂直拆分为主)。
这个方案有这么几个好处:
- 改动相对较小,无需引入新的分布式中间件,甚至是把数据完全迁移到新的分布式数据库。
- 分布式数据库虽然也有对于 MySQL 的协议兼容,但也无法做到 100% 的兼容性,使用分布式中间件也会有类似的限制。
- 仍然可以继续使用已有的工具流程,GitHub 在这方面投入不小,比如说做大表 schema 变更的 gh-ost[3]
当然这个方案的缺点也比较明显:
- 无法像 Sharding 方案一样一经改造,之后就获得理论上没有上限的扩展性。从结果可以看到,经过 2 年的工作,把主库的 load 降低了一半,并不算太多,而且随着 GitHub 业务的持续增长,主库的 load 还是会上去,所以还是要继续做应用库的拆分。不像 Sharding 方案完成之后,在扩展性上基本可以说是一劳永逸。
- 对于业务调优要求是相对较高的,因为数据库本身已经用到了极限,就需要更多应用侧的精细优化。而 Sharding 方案是水平扩展,所以许多时候可以无脑加节点。
GitHub 最终选择了一个渐进式的方案,仍然是基于原生 MySQL 的基础上,在应用侧进行数据库的拆分。
亮 点
吸引笔者眼球的倒也不是拆分选择的方案以及过程,而是在最后的结果中读到了拆分前后的数据比对,尤其是拆分前 mysql1 单集群的数据
In 2019, mysql1 answered 950,000 queries/s on average, 900,000 queries/s on replicas, and 50,000 queries/s on the primary.
Microsoft 以 75 亿美金收购 GitHub 是发生在 2018 年,彼时的 GitHub 已经是全世界流量最大的网站之一,用于支撑这个网站的核心数据库架构还是朴素的一主多备原生 MySQL 集群。不仅 MySQL 能够做到这样,PostgreSQL 同样可以,据笔者了解,世界最大的旅游评论网站 TripAdvisor 直到上市也都是用一主多备的 PostgreSQL 集群支撑的。而这两年协同办公领域最火的产品 Notion 这两天除了公布他们100亿美金估值的融资外,也透露了他们在今年初才进行了 PostgreSQL 的 Sharding。[4]
总 结
通常大家选择分库分表,采用分布式中间件还是直接选用分布式数据库都是为了解决扩展性问题 (Scalability),但是 GitHub 的例子也表明了朴素的一主多备 MySQL 数据库集群一样可以支撑起顶流网站。当然这也不是直接否定分布式中间件 / 数据库的价值,毕竟要像 GitHub 那样把 MySQL 发挥到这个水准也要许多的 DBA 调优,应用架构以及周边工具的配合,而如果中间件尤其是数据库本身就具备原生扩展能力的话,也能省去许多的工作量。毕竟一款开箱即用,能够原生支持水平扩展的数据库产品,他所能节省的工程师成本也是不容忽视的。
现在原生 (Vanilla) 的 MySQL 和 PostgreSQL 本身的性能就很强大,而且每个新版本还会有进一步的改进,如果仅仅是担心将来遇上性能瓶颈,还是要再认真分析一下业务情况以及应用架构,是不是业务体量真的大到要用分布式方案解决。在做技术选型时,单纯的性能指标也只是一个衡量纬度,还要考虑易用性,可运维性等其他技术指标。除了技术指标外,数据库选型也会影响技术团队组织架构的演进方向,采用单体数据库,单体数据库 分布式中间件,分布式数据库,OLTP/OLAP 混合数据库 (HTAP) 也是会引导 Infra 团队走向不同的组织架构。
总之,我们应该采用无聊的技术去构建创新的产品,而不是倒过来。
[1] Partitioning GitHub’s relational databases to handle scale: https://github.blog/2021-09-27-partitioning-githubs-relational-databases-scale/
[2] Hacker News 相关讨论: https://news.ycombinator.com/item?id=28678647
[3] gh-ost: https://github.com/github/gh-ost
[4] Herding elephants: Lessons learned from sharding Postgres at Notion - https://www.notion.so/blog/sharding-postgres-at-notion
作者介绍:
陈天舟, 个人公众号 cloudthought。曾在 Google 硅谷总部云数据库团队担任技术负责人。也在蚂蚁集团负责过整个数据库平台,研发工具,生产力协同工具团队。目前是 bytebase.com 的创始人,研发一款面向工程师和 DBA 的开源数据库 schema 变更协同工具。