Google Ads 如何借助 SQL 数据库支持 47.7 亿用户

265 阅读6分钟

How Google Ads Was Able to Support 4.77 Billion Users With a SQL Database 🔥

原文链接:newsletter.systemdesign.one/p/cloud-spa…

原文作者:Neo Kim

译者:菜小鸟魔王

曾经,有两名大学生打算将他们在大学期间进行的项目以百万美元的价格卖掉。

但他们的计划并未如愿以偿。

于是,他们决定进一步开发这个项目,并将其命名为“谷歌”(Google)。

他们的主要收入来自于广告位(Ads)。

公司的发展速度如同火箭般飙升。

出于对简洁性和可靠性的考虑,他们选择将广告数据存放在MySQL数据库中。

随着用户数量的增加,他们通过在 MySQL 分区来进行扩展。

对 MySQL 进行键范围分区以实现扩展(Key-Range Partitioning of MySQL to Scale)

尽管分区策略暂时缓解了扩展性问题,但新的挑战也随之而来。

以下是他们面临的一些问题:

  1. 可扩展性挑战

随着业务的发展,存储需求急剧上升。

而对MySQL进行重新分区是一个耗时过程,因为这涉及到在不同服务器间转移数据。

然而,他们对系统停机的时间容忍度极低。

这无疑增加了操作的难度。

  1. 事务处理的难题

广告数据需要符合ACID原则。

但在数据库分区之后,保持事务的完整性将变得困难。

可以将事务视为一连串的写入和读取操作。

云Spanner数据库

他们需要一个既具有 NoSQL 的大规模可扩展性,又具备 MySQL ACID 特性的数据库。

于是,他们开发了Spanner —— 一款分布式 SQL 数据库。

具体实现原理如下:

  1. 事务的原子性(Atomicity)

原子性指的是事务的执行要么全部成功,要么全部失败。

换句话说,事务必须同时更新不同分区中的数据。

原子事务的两阶段提交机制

然而,确保所有分区的数据都能提交是比较困难的。

为此,他们采用了两阶段提交(2PC,two-phase commit)协议。

操作流程如下:

  • 准备阶段:协调者(coordinator)询问各相关分区是否已准备好提交。

  • 提交阶段:若所有分区均同意,协调者(coordinator)将指示它们进行提交。

如果有任何分区未准备好,事务将终止。这样便实现了事务的原子性。

最精彩的部分就要来了,准备好了吗?

  1. 一致性保障

他们在全球范围内确保了数据的强一致性。

也就是说,一旦数据在欧洲更新,亚洲看到的数据也将是最新版本。简而言之,读取操作总是能够获取到最新的写入数据。

不同分区跨区域部署

为了提升可扩展性,数据库分区被复制到不同的地理区域。每个区域可以看作是一个独立的地理位置。

但是,为了避免数据冲突,需要在所有副本之间协调写入操作。

因此,他们采用了Paxos算法来选举分区的领导者。分区领导者负责处理写入,而跟随者则负责读取。不同的分区领导者可能会被分配到不同的区域。

可以将Paxos理解为一种在分布式系统中达成共识的机制。

TrueTime架构

通过使用时间戳为写入操作排序,可以简单实现强一致性,这保证了跨服务器数据视图的一致性。

然而,在全球范围内保持服务器时间同步也是一项挑战。

为此,他们引入了TrueTime技术。TrueTime结合了GPS接收器原子钟,能够精确地确定每个数据中心的当前时间。

每台服务器都会每隔30秒与TrueTime同步一次,以确保石英钟的准确性。

读取时通过比较时间戳实现强一致性

以下是读取操作的执行流程:

  1. 请求首先被路由到最近的区域,即使该区域只有跟随者

  2. 跟随者向领导者请求所请求数据的最新时间戳

  3. 跟随者将领导者提供的时间戳与自己的时间戳进行比较

  4. 跟随者随后向客户端返回响应

如果跟随者的数据不是最新的,它将等待领导者同步后再响应。

准备好了吗?让我们继续探索下一项技术。

  1. 事务隔离

事务的隔离性确保了不同事务之间不会相互影响。

写入操作中的数据隔离:两阶段锁机制

在并发事务中,避免数据冲突并非易事。

因此,他们在数据写入过程中采用了两阶段锁(2PL)机制来确保数据隔离。

具体操作流程如下:

  • 增长阶段:事务在获得数据锁后执行读或写操作

  • 收缩阶段:事务完成后,逐步释放所持有的锁

这样做可以有效避免写入时的数据冲突。

读取操作中的快照隔离

同时,他们还运用了快照隔离技术。

这是一种支持无锁读取的多版本并发控制(MVCC)方法。可以将快照隔离视为一种从数据库的某个时间点查看数据的能力。

在读取时,它返回的是数据的某个版本,而不会对正在进行的写入操作造成影响,从而实现了数据隔离。

具体原理如下:

  • 旧数据不会被直接覆盖

  • 而是会写入一个带有TrueTime时间戳的新值

并且,为了节省存储空间,系统会在一段时间后自动清理旧版本的数据。

接下来,让我们继续。

  1. 事务的持久性

持久性确保了已完成事务的结果不会丢失。

使用Paxos算法进行同步写入,以确保数据的持久性

他们通过Paxos算法执行同步写入操作,这样当数据被写入到大多数跟随者节点时,就提供了持久性保障。

然后,数据会基于领导者-跟随者复制技术,被复制到其他跟随者节点。

数据库服务器的高层架构

此外,他们在数据库服务器中实现了计算层和存储层的分离。

计算层负责处理读写操作,而Google Colossus则作为存储层使用。可以将Colossus视为一个为了实现高性能和数据持久性而设计的分布式文件系统。

Spanner 具备 99.999% 的可靠性。

而谷歌在 2023 年从广告业务中获得了高达 2370 亿美元的收入。

并一跃成为全球最有价值的公司之一。