Google Cloud Spanner内部机制

2022-04-02 00:00:00 拆分 数据 节点 时间 区域

过去两天来,我们已经了解了有关Google Cloud Spanner的更多内部信息。我们从Youtube上阅读了Spanner白皮书的某些部分以及深入的内部内容。我们在此处共享了视频链接,但我们希望将所有学习总结在一个地方。特别感谢Deepti Srivastava(Spanner产品经理)在Google Cloud Next Event中介绍了Spanner的深潜课程。

MySQL的痛苦:

在2005年,2006年,Google大规模使用MySQL。Google Adwords是使用90多个MySQL Shards存储数据的大平台之一。由于进行了一些维护,他们重新分配了MySQL群集。这个过程花了2年时间才能完成。Google知道它们的发展非常迅速,而这类数据库在将来会很痛苦。这就是Spanner的诞生方式。

BigTable和Spanner:

一旦他们决定构建分布式的新东西,Big Table团队便是开始为Spanner流程工作的团队。因为BigTable使用分布式过程,存储和高可用性(或其他一些原因)。

巨人:

Colossus是从GFS派生的分布式文件系统。超级数据库需要高性能的文件系统。此项目由BigTable团队启动,BigTable由Colossus提供支持。因此,Spanner也成为了文件系统的巨像。

为什么选择Spanner?

Google Adwords是基于MySQL的堆栈,新系统需要具有关系数据库的基本要素,例如ACID合规性,而不受规模的限制。MySQL的痛苦在于重新分片。因此,他们想要像传统的NoSQL分片这样的分片功能,这些功能将负责重新分片和重新平衡。加上更多可用性,水平扩展和全球分布。

Spanner架构:

Spanner是一个全球数据库系统,每个区域至少需要3个分片。每个分片将位于每个区域中。用Spanner的术语来说,分片称为Split。如果您提供了1个Node Spanner群集,则您将在不同区域上获得另外2个对您不可见的节点。并且计算层和存储层是分离的。Paxos算法用于一次维护一位,其余节点将成为跟随者。

基于分区,我们将在存储层中有更多的拆分(碎片)。每个分片将被复制到其他区域。例如:如果您在A区上有一个名为S1的分片,它将被复制到B区和C区。复制基于Leader跟随器方法进行。因此,Paxos将有助于维持法定人数,并有助于在失败期间选择新的Leader。如果您在此Split上编写内容,则Spanner API会知道Leaders。因此,写入将直接转到具有“前导分割”的区域。每个拆分都有自己的区域。

全球强一致性:

当我观看Spanner的深潜视频时,他们正在讨论强大的一致性。Spanner支持所有节点(全局)之间的强一致性。如果您在美国地区写东西,则可以从亚洲地区或任何其他地区读取相同的数据。他们如何实现这种逻辑?它称为TrueTime。

TrueTime:

Spanner在分布于多个数据中心的全球所有节点之间同步并维持相同的时间。硬件内置原子钟以维持时间。如果您查看服务器硬件机架,则该服务器有4个时间服务器。2台服务器与GPS连接,其余2台与原子振荡器连接。有2种不同的振荡器品牌,可以实现更好的故障转移处理。GPS时间服务器将与振荡器同步,以每30秒间隔同步全球数据中心的时间。

现在,让我们尝试了解这如何TrueTime帮助Spanner保持一致。

与TrueTime的一致性

要了解一致性和TrueTime之间的关系,我们必须了解Spanner中的写操作如何工作。在每次写操作期间,Spanner会拾取当前的TrueTime值,并且此TrueTime时间戳记将为写操作创建一个顺序。因此,每次提交都附带了时间戳。

例如:如果要在节点1上写入数据,它将使用TrueTime时间戳提交数据,并将数据和时间戳复制到其他节点。在所有节点上,此时间戳都相同。假设我们在节点1上提交了此数据,如果您正在从节点B读取相同的数据,那么Spanner API会向Split的负责人询问后提交的数据的时间戳,如果时间戳与Node A的时间戳相匹配,则数据将从节点B返回,否则将等待,直到节点A将数据同步到节点B,然后它将返回数据。

单行写操作的生命周期:

这是单个写入操作的生命周期。我们正在写一行将转到拆分2的行。现在,Spanner API将了解谁是拆分2的节点,然后请求将进入Zone B节点(蓝色指示是)。然后它将获取锁,将其写入拆分。写入完成后,它将请求发送到区域A和C节点以进行写入。它将等待大多数节点的确认。分裂一旦获得了大部分的认可,便会将成功响应发送给客户。

多行写操作:

如果要在单个事务中写入数据,但数据位于不同的拆分中,则Spanner将以不同的方式处理它。例如:我们必须更新2行。

  • 第1行在Split1中-C区是Leader Split
  • 第2行位于Split2中-B区是Leader Split

当我们启动事务时,Spanner API将理解这些行处于不同的拆分中。他们将随机选择一个协调器区域。在我们的示例中,API选择了区域C为协调器区域。对于多行操作将执行以下步骤。

  1. 选择协调器区域。(C区)
  2. 同时获取两个分组上的数据锁。
  3. 在两个拆分上添加新数据。拆分将新数据复制到跟随者拆分。然后从跟随者拆分中获得确认(两个拆分将等待获得确认)。
  4. 然后,区域B拆分将向协调器区域的拆分发送一条消息,表明它已完成更新并准备提交。
  5. 然后,区域C中的Split1将告诉Split2,继续并提交数据。同时,拆分1也将提交。
  6. 提交请求将转到所有拆分(和关注者),并提交数据。
  7. 然后,成功响应将传递给客户。

读操作的寿命:

从Spanner读取数据时,将从近的关注者拆分中获取数据。让我们用一个例子来解释一下。请参考下图。

我们想从MyTable读取值123的数据。此值存储在Split 2中。现在,一旦请求到达Spanner Frontend服务器,它将了解谁是近的关注者拆分,并将请求转发到该拆分。在我们的情况下,区域A是近的拆分。请求到达拆分后,该拆分将请求Leader拆分以获取后提交的TrueTime。然后它将时间戳与自己的时间戳进行比较。如果两者都匹配,它将把数据提供给应用程序。如果时间戳不匹配,则分组将要求跟随者等待,直到将数据同步到该区域。然后拆分将为数据提供服务。

过期/时间限制为:

Spanner支持MVCC。因此,它将旧数据保留一段时间。如果我们的应用程序可以很好地获取旧数据(早于X秒),则无需等待分裂的数据同步。例如,我们必须告诉Split我们使用15秒的旧数据就可以了,然后它将检查提交的时间戳,该时间少于15秒,然后将旧数据提供给应用程序。

多区域Spanner:

上面说明的所有方案都适用于单个区域(区域级别)内的群集。但是,Spanner是为全球规模和多区域部署而构建的。在多区域设置中,体系结构和写/读操作将略有不同。在单区域概念中,我们至少需要3个区域才能创建集群。区域同时支持读取和写入。但是在多区域概念中,一个大洲将充当,而其他大洲将成为追随者。用Spanner的话来说,我们拥有更多地区的欧洲大陆将成为法定人数。所有写操作都将到达该大陆的任何地区。在仲裁大陆中,将有2个区域托管数据节点,而1个区域将托管见证服务器进行故障转移。其他大洲将具有只读副本节点。

多区域一致性:

在多区域群集中,写操作始终在Quorum大陆上执行。假设美国地区是R / W大陆,那么如果您从美国地区发送写请求,则Spanner API会将其发送到近的地区,一旦提交了数据,则成功响应将转到客户。如果您要从亚洲地区发送写请求,则亚洲地区的API服务器会将请求放入Google的内部网络中,然后将请求发送到美国地区的API服务器。然后,该美国地区API服务器将提交数据,并将成功响应发送给亚洲地区客户。

对于读取,该过程与单个区域的概念相同,如果TrueTime匹配,则将从本地区域提供数据,否则将等待直到数据同步到本地区域然后再提供给客户端。

结论:

我们介绍了Spanner的大多数内部概念。但是,在Cloud Spanner中还有很多事情要学习。请参考下面的Google Cloud Next活动视频链接。

来源 https://zhuanlan.zhihu.com/p/138800233

相关文章