分布式系统Spanner.docx
《分布式系统Spanner.docx》由会员分享,可在线阅读,更多相关《分布式系统Spanner.docx(15页珍藏版)》请在冰豆网上搜索。
分布式系统Spanner
全球级分布式数据库GoogleSpanner原理介绍与分析
1摘要
Spanner是Google的分布式数据库(Globally-DistributedDatabase)。
其扩展性能达到了令人咋舌的全球级,可以扩展到数百万的机器,数已百计的数据中心,上万亿的行。
除了夸张的扩展性之外,它还能同时通过同步复制和多版本来满足外部一致性,在CAP三者之间完美平衡。
Spanner设计中一个亮点特性就是TrueTime。
在时间API中明确给出时钟不确定性,以更加强壮的时间语义来构建分布式系统。
本文对GoogleSpanner从提出背景、设计、原理应用等方面进行了详细的介绍。
在本文的最后,作者对GoogleSpanner进行了分析,就CAP理论和其优点谈及了自己的看法。
关键字:
分布式系统、数据库、TrueTime、RDBMS
2ABSTRACT
SpannerisGoogle'sglobaldistributeddatabase.Theexpansionperformancereachedgloballevelthatcanbeextendedtomillionsofmachines,hundredsofdatacenters,trilliondatarows.Inadditiontotheamazingexpansionperformance,Spannercanmeettheexternalconsistencyboththroughsynchronizedreplicationandmultiversion,achievedtheperfectbalancebetweenthethreeCAPtheorem.OneofthehighlightsinthedesignoftheSpannerisTrueTime.InthistimeAPI,theuncertaintyoftheclockisdefined,andthedistributedsystemisconstructedwithamorerobusttimesemantics.
Inthispaper,thebackground,design,principleandapplicationofSpannerGoogleareintroducedindetail.Attheendofthispaper,theauthoranalyzestheGoogleSpanner,andtalkedabouthisownviewsontheCAPtheoryanditsadvantages.
Keywords:
DistributedSystem、Database、TrueTime、RDBMS
目录
1摘要1
2ABSTRACT2
3绪论1
3.1背景介绍1
3.2Spanner的前身——著名的Bigtable1
3.3可容错可扩展的RDBMS-F12
3.4Spanner简介2
4原理与实现3
4.2Spanserver软件栈4
4.3目录和放置5
4.4数据模型7
4.5TrueTimeAPI8
5Spanner的应用9
6总结11
6.1CAP理论11
6.2Spanner的优点12
7参考文献14
3绪论
背景介绍
Google是全球著名的互联网公司,拥有全球最大的谷歌搜索引擎,全球广泛使用的谷歌分析、谷歌地球、谷歌地图等核心业务。
多种不同的业务对数据存储系统提出了不同的要求,一些应用拥有巨大的数据规模,一些应用要求较低的读写延迟,甚至一些应用同时对两者提出了很高的要求,例如广泛使用的谷歌分析服务。
如何使用一种统一的方式来存储各种类型的数据是谷歌公司面临的巨大问题。
此外,谷歌每天要处理海量的服务请求,如何从海量的数据中快速寻找需要的数据,降低服务的延迟?
谷歌对数据存储系统具有很多需求,例如数据存储的可靠性,高速的数据检索与读取,要能够存储海量的数据(PB级)并且能够保存数据的多个版本。
谷歌的需求决定了分布式系统必须具有强大的可扩展能力,可以随时动态的添加删除的机器,以满足动态的性能需求。
此外,存储系统的一致性,分布式事物的支持显得越来越重要。
Spanner的前身——著名的Bigtable
谷歌在2006年发布了Bigtable,Bigtable是一个用于管理结构化数据的基于GFS和Chubby的分布式存储系统。
Bigtable的设计目的是可靠地适应PB级别的数据和成千上万台机器。
Bigtable实现了下面的几个目标:
广泛的适用性(能够支持Google系列产品的存储需求)、可扩展(能根据需要随时加入或撤销服务器)、高性能和高可用性(单个节点的损坏不会影响系统的正常运行),有超过60个Google的产品和项目在使用Bigtable,包括GoogleAnalytics、GoogleFinance、PersonalizedSearch和GoogleEarth。
这些产品使用Bigtable完成不同的工作负载需求,从面向吞吐量的批处理作业到对终端用户而言延时敏感的数据服务。
实际应用证明了Bigtable相对Hbase等分布式系统具有高吞吐量,低延迟等特点,对全球的数据存储系统具有深远的影响。
Google官方认为Spanner是下一代Bigtable,也是Megastore的继任者。
可容错可扩展的RDBMS-F1
和众多互联网公司一样,在早期Google大量使用了MySQL。
MySQL是单机的,可以用Master-Slave来容错,分区来扩展。
但是需要大量的手工运维工作,有很多的限制。
因此Google在Spanner的基础上开发了一个可容错可扩展的RDBMS——F1。
和一般的分布式数据库不同,F1对应RDMS应有的功能,毫不妥协。
起初F1是基于MySQL的,不过会逐渐迁移到Spanner。
F1有如下特点:
●7×24高可用,哪怕某一个数据中心停止运转,仍然可用。
●可以同时提供强一致性和弱一致性
●搞可扩展性
●支持SQL
●事务提交延迟50-100ms,读延迟5-10ms,高吞吐
众所周知GoogleBigTable是重要的NoSql产品,提供很好的扩展性,开源世界有HBase与之对应。
为什么Google还需要F1,而不是都使用BigTable呢?
因为BigTable提供的最终一致性,一些需要事务级别的应用无法使用。
同时BigTable还是NoSql,而大量的应用场景需要有关系模型。
就像现在大量的互联网企业都使用Mysql而不愿意使用HBase,因此Google才有这个可扩展数据库的F1。
而Spanner就是F1的至关重要的底层存储技术。
Spanner简介
Spanner是Google的全球级的分布式数据库。
Spanner的扩展性达到了令人咋舌的全球级,可以扩展到数百万的机器,数已百计的数据中心,上万亿的行。
更给力的是,除了夸张的扩展性之外,他还能同时通过同步复制和多版本来满足外部一致性,可用性也是很好的,在CAP三者之间完美平衡。
应用可以借助于Spanner来实现高可用性,通过在一个洲的内部和跨越不同的洲之间复制数据,保证即使面对大范围的自然灾害时数据依然可用。
谷歌最初的客户是F1,一个谷歌广告后台的重新编程实现。
F1使用了跨越美国的5个副本。
绝大多数其他应用很可能会在属于同一个地理范围内的3-5个数据中心内放置数据副本,采用相对独立的失败模式。
也就是说,许多应用都会首先选择低延迟,而不是高可用性,只要系统能够从1-2个数据中心失败中恢复过来。
Spanner的主要工作,就是管理跨越多个数据中心的数据副本,但是,在分布式系统体系架构之上设计和实现重要的数据库特性方面,谷歌也花费了大量的时间。
尽管有许多项目可以很好地使用BigTable,谷歌也不断收到来自客户的抱怨,客户反映BigTable无法应用到一些特定类型的应用上面,比如具备复杂可变的模式,或者对于在大范围内分布的多个副本数据具有较高的一致性要求。
由于上述多个方面的因素,Spanner已经从一个类似BigTable的单一版本的键值存储,演化成为一个具有时间属性的多版本的数据库。
数据被存储到模式化的、半关系的表中,数据被版本化,每个版本都会自动以提交时间作为时间戳,旧版本的数据会更容易被垃圾回收。
应用可以读取旧版本的数据。
Spanner支持通用的事务,提供了基于SQL的查询语言。
Spanner可以为事务分配全球范围内有意义的提交时间戳,即使事务可能是分布式的。
这些时间戳反映了事务序列化的顺序。
除此以外,这些序列化的顺序满足了外部一致性的要求:
如果一个事务T1在另一个事务T2开始之前就已经提交了,那么,T1的时间戳就要比T2的时间戳小。
Spanner是第一个可以在全球范围内提供这种保证的系统。
实现这种特性的关键技术就是一个新的TrueTimeAPI及其实现。
这个API可以直接暴露时钟不确定性,Spanner时间戳的保证就是取决于这个API实现的界限。
如果这个不确定性很大,Spanner就降低速度来等待这个大的不确定性结束。
谷歌的簇管理器软件提供了一个TrueTimeAPI的实现。
这种实现可以保持较小的不确定性(通常小于10ms),主要是借助于现代时钟参考值(比如GPS和原子钟)。
4原理与实现
一个Spanner部署称为一个Universe。
假设Spanner在全球范围内管理数据,那么,将会只有可数的、运行中的Universe。
当前正在运行一个测试用的Universe,一个部署/线上用的Universe和一个只用于线上应用的Universe。
Spanner被组织成许多个Zone的集合,每个Zone都大概像一个BigTable服务器的部署。
Zone是管理部署的基本单元。
Zone的集合也是数据可以被复制到的位置的集合。
当新的数据中心加入服务,或者老的数据中心被关闭时,Zone可以被加入到一个运行的系统中,或者从中移除。
Zone也是物理隔离的单元,在一个数据中心中,可能有一个或者多个Zone,例如,属于不同应用的数据可能必须被分区存储到同一个数据中心的不同服务器集合中。
图4-1Spanner服务器组织
图4-1显示了在一个Spanner的Universe中的服务器。
一个Zone包括一个Zonemaster,和一百至几千个Spanserver。
Zonemaster把数据分配给Spanserver,Spanserver把数据提供给客户端。
客户端使用每个Zone上面的locationproxy来定位可以为自己提供数据的Spanserver。
Universemaster和Placementdriver,当前都只有一个。
Universemaster主要是一个控制台,它显示了关于Zone的各种状态信息,可以用于相互之间的调试。
Placementdriver会周期性地与Spanserver进行交互,来发现那些需要被转移的数据,或者是为了满足新的副本约束条件,或者是为了进行负载均衡。
Spanserver软件栈
本部分主要讲述Spanserver实现,来解释复制和分布式事务是如何被架构到基于BigTable的实现之上的。
图4-2显示了软件栈。
在底部,每个Spanserver负责管理100-1000个称为Tablet的数据结构的实例,类似于BigTable中的Tablet,也实现了下面的映射:
(key:
string,timestamp:
int64)→string
图4-2Spanserver软件栈
与BigTable不同的是,Spanner会把时间戳分配给数据,这种非常重要的方式,使得Spanner更像一个多版本数据库,而不是一个键值存储。
一个tablet的状态是存储在类似于B-树的文件集合和日志中,所有这些都会被保存到一个分布式的文件系统中,这个分布式文件系统被称为Colossus。
他是第二代GFS,对应开源世界的新HDFS,GFS是著名的分布式文件系统。
Colossus可以自动分区Metadata,使用Reed-Solomon算法来复制,可以将原先的3份减小到1.5份,提高写的性能,降低延迟。
对于每个是Leader的副本而言,每个Spanserver会实现一个锁表来实现并发控制。
这个锁表包含了两阶段锁机制的状态:
它把键的值域映射到锁状态上面。
注意,采用一个长寿命的Paxos领导者,对于有效管理锁表而言是非常关键的。
在BigTable和Spanner中,谷歌都专门为长事务做了设计,比如,对于报表操作,可能要持续几分钟,当存在冲突时,采用乐观并发控制机制会表现出很差的性能。
对于那些需要同步的操作,比如事务型的读操作,需要获得锁表中的锁,而其他类型的操作则可以不理会锁表。
目录和放置
一个目录是数据放置的基本单元。
属于一个目录的所有数据,都具有相同的副本配置。
当数据在不同的Paxos组之间进行移动时,会一个目录一个目录地转移,如图4-3所示。
Spanner可能会移动一个目录从而减轻一个Paxos组的负担,也可能会把那些被频繁地一起访问的目录都放置到同一个组中,或者会把一个目录转移到距离访问者更近的地方。
当客户端操作正在进行时,也可以进行目录的转移。
可以预期在几秒内转移50MB的目录。
图4-3目录是移动的基本单元
一个Paxos组可以包含多个目录,这意味着一个Spannertablet是不同于一个BigTabletablet的。
一个Spannertablet没有必要是一个行空间内按照词典顺序连续的分区,相反,它可以是行空间内的多个分区。
之所以做出这个决定,是因为这样做可以让多个被频繁一起访问的目录被整合到一起。
Movedir是一个后台任务,用来在不同的Paxos组之间转移目录。
Movedir也用来为Paxos组增加和删除副本,因为Spanner目前还不支持在一个Paxos内部进行配置的变更。
Movedir并不是作为一个事务来实现,这样可以避免在一个块数据转移过程中阻塞正在进行的读操作和写操作。
相反,Movedir会注册一个事实,表明它要转移数据,然后在后台运行转移数据。
当它几乎快要转移完指定数量的数据时,就会启动一个事务来自动转移那部分数据,并且为两个Paxos组更新元数据。
一个目录也是一个应用可以指定的地理复制属性(即放置策略)的最小单元。
谷歌的放置规范语言的设计,把管理复制的配置这个任务单独分离出来。
管理员需要控制两个维度:
副本的数量和类型,以及这些副本的地理放置属性。
他们在这两个维度里面创建了一个命名选项的菜单。
通过为每个数据库或单独的目录增加这些命名选项的组合,一个应用就可以控制数据的复制。
例如,一个应用可能会在自己的目录里存储每个终端用户的数据,这就有可能使得用户A的数据在欧洲有三个副本,用户B的数据在北美有5个副本。
数据模型
Spanner基于模式化的半关系表的数据模型,支持查询语言和通用事务。
在Spanner中需要支持SQL类型的查询语言,也很显然是非常必要的,因为在BigTable中跨行事务的缺乏来导致了用户频繁的抱怨。
应用的数据模型是架构在被目录桶装的键值映射层之上。
一个应用会在一个Universe中创建一个或者多个数据库。
每个数据库可以包含无限数量的模式化的表。
每个表都和关系数据库表类似,具备行、列和版本值。
Spanner的查询语言,是在SQL上做了一些扩展。
Spanner的数据模型不是纯粹关系型的,它的行必须有名称。
更准确地说,每个表都需要有包含一个或多个主键列的排序集合。
这种需求,让Spanner看起来仍然有点像键值存储:
主键形成了一个行的名称,每个表都定义了从主键列到非主键列的映射。
当一个行存在时,必须要求已经给行的一些键定义了一些值(即使是NULL)。
采用这种结构是很有用的,因为这可以让应用通过选择键来控制数据的局部性。
图4-4图片元信息Spanner举例,层次通过INTERLEAVEIN实现
图4-4包含了一个Spanner模式的实例,它是以每个用户和每个相册为基础存储图片元数据。
每个Spanner数据库必须被客户端分割成一个或多个表的层次结构。
客户端应用会使用INTERLEAVEIN语句在数据库模式中声明这个层次结构。
这个层次结构上面的表,是一个目录表。
目录表中的每行都具有键Key,和子表中的所有以Key开始(以字典顺序排序)的行一起,构成了一个目录。
ONDELETECASCADE意味着,如果删除目录中的一个行,也会级联删除所有相关的子行。
这个图也解释了这个实例数据库的交织层次,例如Albums(2,1)代表了来自Albums表的、对应于user_id=2和album_id=1的行。
这种表的交织层次形成目录,是非常重要的,因为它允许客户端来描述存在于多个表之间的位置关系,这对于一个分片的分布式数据库的性能而言是很重要的。
没有它的话,Spanner就无法知道最重要的位置关系。
TrueTimeAPI
图4-5TrueTimeAPI参数t是时间戳类型
图4-5列出了API的方法。
TrueTime会显式地把时间表达成TTinterval,这是一个时间区间,具有界限的时间不确定性(不像其他的标准时间接口,没有为客户端提供“不确定性”这种概念)。
时间区间的端点是TTstamp类型。
TT.now()方法会返回一个TTinterval,该区间可以包含调用时的绝对时间。
在底层,TrueTime使用的时间是GPS和原子钟。
TrueTime使用两种类型的时间,是因为它们有不同的失败模式。
GPS参考时间的弱点是天线和接收器失效、局部电磁干扰和相关失败(比如设计上的缺陷导致无法正确处理闰秒和电子欺骗),以及GPS系统运行中断。
原子钟也会失效,不过失效的方式和GPS无关,不同原子钟之间的失效也没有彼此关联。
由于存在频率误差,在经过很长的时间以后,原子钟都会产生明显误差。
TrueTime是由每个数据中心上面的许多timemaster机器和每台机器上的一个timeslavedaemon来共同实现的。
大多数master都有具备专用天线的GPS接收器,这些master在物理上是相互隔离的,这样可以减少天线失效、电磁干扰和电子欺骗的影响。
剩余的master(称为Armageddonmaster)则配备了原子钟。
一个原子钟并不是很昂贵:
一个Armageddonmaster的花费和一个GPSmaster的花费是同一个数量级的。
所有master的时间参考值都会进行彼此校对。
每个master也会交叉检查时间参考值和本地时间的比值,如果二者差别太大,就会把自己驱逐出去。
在同步期间,Armageddonmaster会表现出一个逐渐增加的时间不确定性,这是由保守应用的最差时钟漂移引起的。
GPSmaster表现出的时间不确定性几乎接近于0。
每个daemon会从许多master中收集投票,获得时间参考值,从而减少误差。
被选中的master中,有些master是GPSmaster,是从附近的数据中心获得的,剩余的GPSmaster是从远处的数据中心获得的;还有一些是Armageddonmaster。
Daemon会使用一个Marzullo算法的变种,来探测和拒绝欺骗,并且把本地时钟同步到非撒谎master的时间参考值。
为了免受较差的本地时钟的影响,Spanner会根据组件规范和运行环境确定一个界限,如果机器的本地时钟误差频繁超出这个界限,这个机器就会被驱逐出去。
5Spanner的应用
Spanner在2011年早期开始进行在线负载测试,它是作为谷歌广告后台F1实现的一部分。
这个系统的后台最开始是基于MySQL数据库,在许多方面都采用手工数据分区。
未经压缩的数据可以达到几十TB,虽然这对于许多NoSQL实例而言数据量是很小的,但是,对于采用数据分区的MySQL而言,数据量是非常大的。
MySQL的数据分片机制,会把每个客户和所有相关的数据分配给一个固定的分区。
这种布局方式,可以支持针对单个客户的索引构建和复杂查询处理,但是,需要了解一些商业知识来设计分区。
随着客户数量的增长,对数据进行重新分区,代价是很大的。
最近一次的重新分区,花费了两年的时间,为了降低风险,在多个团队之间进行了大量的合作和测试。
这种操作太复杂了,无法常常执行,由此导致的结果是,团队必须限制MySQL数据库的增长,方法是,把一些数据存储在外部的Bigtable中,这就会牺牲事务和查询所有数据的能力。
F1团队选择使用Spanner有几个方面的原因。
首先,Spanner不需要手工分区。
其次,Spanner提供了同步复制和自动失败恢复。
在采用MySQL的master-slave复制方法时,很难进行失败恢复,会有数据丢失和当机的风险。
再次,F1需要强壮的事务语义,这使得使用其他NoSQL系统是不实际的。
应用语义需要跨越任意数据的事务和一致性读。
F1团队也需要在他们的数据上构建二级索引(因为Spanner没有提供对二级索引的自动支持),也有能力使用Spanner事务来实现他们自己的一致性全球索引。
所有应用写操作,现在都是默认从F1发送到Spanner。
而不是发送到基于MySQL的应用栈。
F1在美国的西岸有两个副本,在东岸有三个副本。
这种副本位置的选择,是为了避免发生自然灾害时出现服务停止问题,也是出于前端应用的位置的考虑。
实际上,Spanner的失败自动恢复,几乎是不可见的。
在过去的几个月中,尽管有不在计划内的机群失效,但是,F1团队最需要做的工作仍然是更新他们的数据库模式,来告诉Spanner在哪里放置Paxos领导者,从而使得它们尽量靠近应用前端。
Spanner时间戳语义,使得它对于F1而言,可以高效地维护从数据库状态计算得到的、放在内存中的数据结构。
F1会为所有变更都维护一个逻辑历史日志,它会作为每个事务的一部分写入到Spanner。
F1会得到某个时间戳下的数据的完整快照,来初始化它的数据结构,然后根据数据的增量变化来更新这个数据结构。
图5-1F124小时内平均操作延迟
图5-1显示了从F1服务器来测量的Spanner操作的延迟。
在东海岸数据中心的副本,在选择Paxos领导者方面会获得更高的优先级。
图5-1中的数据是从这些数据中心的F1服务器上测量得到的。
写操作延迟分布上存在较大的标准差,是由于锁冲突引起的肥尾效应。
在读操作延迟分布上存在更大的标准差,部分是因为Paxos领导者跨越了两个数据中心,只有其中的一个是采用了固态硬盘的机器。
6总结
总的来说,Spanner对来自两个研究群体的概念进行了结合和扩充:
一个是数据库研究群体,包括熟悉易用的半关系接口,事务和基于SQL的查询语言;另一个是系统研究群体,包括可扩展性,自动分区,容错,一致性复制,外部一致性和大范围分布。
自从Spanner概念成形,谷歌花费了5年以上的时间来完成当前版本的设计和实现。
花费这么长的时间,一部分原因在于慢慢意识到,Spanner不应该仅仅解决全球复制的命名空间问题,而且也应该关注Bigtable中所丢失的数据库特性。
Spanner设计中一个亮点特性就是TrueTime。
在时间API中明确给出时钟不确定性,可以以更加强壮的时间语义来构建分布式系统。
此外,因为底层的系统在时钟不确定性上采用更加严格的边界,实现更强壮的时间语义的代价就会减少。
作为一个研究群体,谷歌在设计分布式算法时,不再依赖于弱同步的时钟和较弱的时间API。
CAP理论
目前,NoSQL和文档数据库成为关系数据库的