Spanner: Google’s Globally-Distributed Database 总结

零、前言

这段时间小组打算讨论Spanner这篇论文,花了好几天时间研究了一下,这里面涉及不少知识盲区,(也有不少和6.824中的lab实验相通的地方) ,在这里总结一波,希望可以便人便己。

一、简介

Spanner是Google公司设计开发的一套可扩展的, 高可用的, 可全球部署的分布式数据库系统.(谷歌号称它是世界上第一个可以在全球范围内进行数据分布式管理并且支持外部一致性分布式事务的数据库产品)。Spanner有以下特性:

  • 提供了基于SQL的查询接口, 使用强类型的schema, 提供了类型RDS的体验.
  • 一定程度上支持垂直sharding, 用户可以通过INTERLEAVE语法定义相关的两个table的记录存放在同一个spanserver. 带来的好处是形成了数据的Locality
  • 可以自动对数据进行水平sharding, 并对每个shard维护一定的数量的副本, 通过Multi-Paxos保证一致性, 这些副本可以分散在全球不同地域.
  • 支持Snapshot Isolation, 通过2PL保证多个并发事务的Serializability. 另外, 对于涉及多个shard的xa事务, 通过2PC保证Serializability.
  • 保证External Consistency, 也就是说如果事务T1提交后, 事务T2才开始提交, 那么T2的timestamp一定大于T1的timestamp.
  • 设计了一个新颖的TrueTime API (这个时间API在承认并且暴露了时间的不确定性),上面所述的很多特性都需要依赖于这个TrueTime API。

注:以上特性摘自网络,很多到目前为止,我也不是很理解。| ╮(╯▽╰)╭

 

二、关于架构

2.1 整体架构

在这里插入图片描述
一个Spanner的整体架构如上图所示。一个Spanner整体系统叫做一个universe(google起名字都比较大气)。它主要有以下几部分组成:

  1. universemaster: 是一个控制台, 监控universe里所有zone状态信息, 用于debug
  2. placement driver: 帮助维持特定副本数量,自动搬迁数据, 实现负载均衡
  3. a set of zones:Zone是系统的主体,具体的数据访问和控制都在一个个zone里。一个数据中心可能含有一个或多个zone。它又细分为以下几个部分:
	3.1 zonemaster:zone上的管理者,用于管理spanserver上的数据
	3.2 a set of spanservers:提供具体的数据存储和访问。
	3.3 location proxy:位置代理,用于给client提供数据的位置信息,client要先访问它来定位需要访问的spanserver

2.2 Spanserver软件架构

上面2.1 介绍的是整体的Spanner框架,下面介绍对于Spanner server的软件架构。
在这里插入图片描述

每一个replica group 里的副本为上图中的一列。如上图中红色标注的部分。 其逻辑数据主要是存储在一个叫做tablet的数据结构体中。可以简单的把看成一个map集合:
在这里插入图片描述
tablet的底层是存储在一个叫做Colossus (GFS的successor)的文件系统上的。

同时,每个replica都运行着paxos共识协议,用来在副本组之间保持数据的一致性。

对于副本组的leader来说,其还需要维护一个lock table ,也就是一系列的KV: key—>lock-states 。 用来事务处理中的2PL。 同时,leader replica 上还实现了transaction manager, 这个模块是用来支持分布式事务的。即事务如果涉及多个replica groups ,replica groups 之间的leader 会相互之间进行协调。也就是上图中蓝色所圈出来的部分。

note:
1、(注意,上面所示的的架构方案不是针对于一台spanner server上运行的,它一般涉及多个spanner server,有可能横跨多个Datacenter。 确切的说,它是一个逻辑上的副本组 (replication group ))。 下面两幅图看的可能更清晰些。

在这里插入图片描述
在这里插入图片描述
2、paper中还介绍了directory的概念。它只是抽象出来的数据的一种组织方式,如下两幅图所示,对于文章整体的把握不是太重要,在此就不过多介绍了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
 


三、关于数据模型

说实话,关于数据模型这一节,我看的不是很懂。只能从表层谈谈spanner的数据模型。
根据论文所述:spanner中数据模型由以下特点:

  1. 结构化的半关系型表
  2. 支持查询语言
  3. 支持通用事务

以上的三个特点要么是由于已经形成的用户需求,要么是由于目前的产品不符合用户的需求(论文中有详述、在这就不赘述了)。

传统的 RDBMS例如MySQL采用关系模型,有丰富的功能,支持SQL查询语句。而NoSQL数据库多是在key-value存储之上增加有限的功能,如列索引、范围查询等,但具有良好的可扩展性。Spanner继承了Megastore的设计,数据模型介于RDBMS和NoSQL之间,提供树形、层次化的数据库schema,一方面支持类SQL的查询语言,提供表连接等关系数据库的特性,功能上类似于RDBMS;另一方面整个数据库中的所有记录都存储在 同一个key-value大表中,实现上类似于BigTable,具有NoSQL系统的可扩展性。

在Spanner中,应用可以在一个数据库里创建多个表,同时需要指定这些表之间的层次关系。例如,下图中创建的两个表——用户表Users和相册表Albums,并且指定用户表是相册 表的父节点。父节点和子节点间存在着一对多的关系,用户表中的一条记录一个用户对应着相册表中的多条记录多个相册。此外,要求子节点的主键必须以 父节点的主键作为前缀。例如,用户表的主键用户ID就是相册表主键用户ID+相册ID的前缀。
在这里插入图片描述
上面的两个SQL语句看似创建了两张表:Users和Albums,但实际上Spanner将它们合并存储。注意第二张表的建表语句使用了多主键:uid和aid,并且通过“INTERLEAVE IN PARENT …”语句表示uid与Users中的主键uid一致。这意味着,Album中的多条uid相同的记录,是嵌套在Users表的一条uid记录之下的。同一个user之下的所有子数据,就构成了一个directory。论文并没有描述表中的非主键如何存储,因此只能推测它们存储在所对应主键之后,即如下结构:
在这里插入图片描述

note:对于这种层次化、类似于树形结构的数据模型来说,关系相近的数据可以存储在一起,这样存取就会利用一些locality的优势,相应的提高性能。 好了,我了解的目前也就这些了。 ╮(╯▽╰)╭

 


四、关于时间

关于时间,它是一个非常大的话题。即使在分布式领域,也是一个big topic。 据我现在了解的知识,分布式领域中的时间问题归结来就是每个进程(或者说每个结点)有不同的时间参考系。就目前的技术来说,还未做到在计算机网络中的各个节点可以有一个绝对同步的时间来参考。 详细的关于分布式领域时钟讨论可以参照【3】、【4】。

对于Spanner来说,它的一个突出的特点就是TrueTime API。 这个TrueAPI 说起来比较复杂,就我目前的水平估计可能讲不了。 下面主要从一个很粗的方面说些我的总结和看法,详细的可以参考paper和【5】。

note:Spanner系统中的TrueTime 是综合利用了硬件(主要是原子钟和GPS)和软件(API),来实现的一种系统时间机制,这种时间机制保证了机器间的时间差不超过ε,从某种程度上把各个节点的时钟拉到了同一个“时钟参考系”(其实确切的说应该是利用延时,来达到事务之间不重叠的目的),让不同的结点发生的事件可以进行因果比较(也就是谁发生在前、谁发生在后)。

 

五、关于并发控制

并发控制是数据库系统中必可缺少的一环,对于支持事务机制的数据库来说,其都需要保证ACID。而并发控制涉及的大部分就是其中的I(Isolation:隔离性)。所谓数据库中隔离性,简单来说意味着并发执行的多个事务相互隔离,他们不能相互交叉。

从事务的跨度来说,spanner中的事务可以又分为两种:一种是跨多个replica group的事务(类似于单系统中涉及到多个对象的事务处理),另一种是仅在单个replica group中的事务。

从事务的读写性质来说,它将事务分为两类读写事务(Read Write Transaction)与只读事务(Read Only Transaction)。 其中只读事务又分为三类:

  1. Snapshot Transaction(强读)
  2. Client-chosen Timestap Read(client指定过期的某个timestamp去读取)
  3. Client-chosen Bound Read(client指定一个不能超过的最早timestamp去读取)

下面简单说说读写事务和只读事务涉及到的内容:

5.1 读写事务(Read Write Transaction)

如上所述,读写事务分为两种:
(1)、单个replica group的事务。
(2)、涉及多个replica group的事务。
其中后者要使用2PC(两阶段提交),前者要使用2PC的退化版本1PC.

下图所示为读写事务的简要流程图。
在这里插入图片描述

5.1.1 单个replica group的读写事务流程(1PC)

主要的请求流程如下图所示
在这里插入图片描述
注意:上图的流程图只是从spanner接收到client的commit开始。

1PC的读写事务的流程如下:

(1)、Client读数据,立即将读取请求发送到Spanner
(2)、Client读数据,立即将读取请求发送到Spanner
(3)、Spanner收到读取请求,为数据加读锁,加锁时如果发现此数据已经被上了写锁,则不能立即上锁,需要等待上了写锁的事务提交后才能继续上锁
(4)、Client写数据,此时只写到本地buffer
(5)、Client完成读写,也就是在SDK中调用commit时,会由client将buffer中的所有Writes发到Spanner
(6)、Spanner开始获取写锁并写日志
(7)、写锁获取完成并写完日志后,再次检查读锁是否还存在(因为可能已经被伤停等待机制给abort掉了),如果不存在,此事务应该abort
(8)、主副本(leader replica)使用TrueTime为此次事务生成一个timestamp,作为commit timestamp
Leader replica(读写事务只能发生在Leader)将log复制给其他replica,同时进行commit-wait,因为TrueTime是一段时间区间,是有误差的,为了保证外部一致性,也就是它提交后,对所有服务器,这个事务都是过去时了,才能提交,commit-wait的实际开销并不大,因为在commit-wait的同时也在进行log的复制,其中空转的时间是非常少的,当大多数replica都复制成功后,并且commit-wait结束,可以向client返回事务已经成功commit,同时apply事务变更到状态机并释放锁。

5.1.2多个replica group的读写事务流程(2PC)

2PC的读写事务流程主要是由于单replica Group的事务变成了多replica Group事务,需要增加协调者,会增加以下步骤:

(1)、client会负责发起2PC,在发送Writes到Spanner时,client会先查找到自己应该分别把Writes发送到哪些服务器,将Writes分别发送给他们,并且client会从这些Leader Replica中选一个作为Coordinator(读写事务只能发生在Leader,因此这里不讨论其他replica)。
(2)、在每个Participant成功获取所有写锁后,会生成一个prepare timestamp,然后通过Paxos将log(其中包含了锁),复制到大多数副本,然后将prepare timestamp发送给Coordinator,表示自己ok
(3)、Coordinator收到所有Participant的prepare timestamp后,会生成一个commit timestamp,这个timestamp一定会大于所有prepare timestamp,并大于TT.now().latest
(4)、Coordinator会在commit-wait结束之后才将commit指令发给Participant

流程图如下所示:
在这里插入图片描述

5.2 只读事务(Read Only Transaction)

关于spanner的只读事务,其主要是基于基于MVCC,用用Snapshot Isolation的方式来执行。 论文中对于这单说的也不是很详细,我查了几份资料,也没搞的太清楚这个MVCC,快照级别的隔离方式具体是怎么运行的,只知道事务从MVCC数据库一致性快照中读取时,它会忽略那些在创建快照时尚未提交的事务的写入。 关于MVCC,我从DDIA这本书上查到了一个例子:如下图所示。
在这里插入图片描述

据我现在的了解,我估计是spanne会保存不同版本的对象,然后根据client发来的请求,返回不同时间点的对象。 具体详细的内容,还待以后研究。

 


六、参考

【1】、解读Google Spanner
【2】、 Spanner技术分析
【3】、逻辑时钟 - 如何刻画分布式中的事件顺序
【4】、线性一致性与全序广播------《Designing Data-Intensive Applications》读书笔记12
【5】、简单解释Spanner的TrueTime在分布式事务中的作用
【6】、关于Spanner中的TrueTime和Linearizability
【7】、Spanner十问

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值