完成对 Google Dremel 原理的分析后,EMC 中国研究院的研究员颜开又在自己博客上分析了 Google 的全球级分布式数据库 Spanner ,他重点分析了 Spanner 的背景、设计和并发控制。
在简介中,颜开指出:
Spanner 的扩展性达到了令人咋舌的全球级,可以扩展到数百万的机器,数已百计的数据中心,上万亿的行。更给力的是,除了夸张的扩展性之外,他还能同时通过同步复制和多版本来满足外部一致性,可用性也是很好的。冲破 CAP 的枷锁,在三者之间完美平衡。
接下来,他提到:
Spanner 能做到这些,离不开一个用 GPS 和原子钟实现的时间 API。这个 API 能将数据中心之间的时间同步精确到 10ms 以内。因此有几个给力的功能:无锁读事务,原子 schema 修改,读历史数据无 block。
在背景分析部分,颜开认为:Spanner 在 Google 的定位,处于 F1 和 GFS 之间。
颜开这样介绍 F1:
一个可容错可扩展的 RDBMS——F1。和一般的分布式数据库不同,F1 对应 RDMS 应有的功能,毫不妥协。起初 F1 是基于 Mysql 的,不过会逐渐迁移到 Spannerr。
F1 有如下特点:
- 7×24 高可用。哪怕某一个数据中心停止运转,仍然可用。
- 可以同时提供强一致性和弱一致。
- 可扩展
- 支持 SQL
- 事务提交延迟 50-100ms,读延迟 5-10ms,高吞吐
至于为什么 Google 不用 BigTable,颜开的分析是:
因为 BigTable 提供的最终一致性,一些需要事务级别的应用无法使用。同时 BigTable 还是 NoSql,而大量的应用场景需要有关系模型。就像现在大量的互联网企业都使用 Mysql 而不愿意使用 HBase,因此 Google 才有这个可扩展数据库的 F1。而 Spanner 就是 F1 的至关重要的底层存储技术。
颜开又介绍了第二代 GFS——Colossus。
初代 GFS 是为批处理设计的。对于大文件很友好,吞吐量很大,但是延迟较高。所以使用他的系统不得不对 GFS 做各种优化,才能获得良好的性能。
Colossus 是第二代 GFS。Colossus 是 Google 重要的基础设施,因为他可以满足主流应用对 FS 的要求。Colossus 的重要改进有:
- 优雅 Master 容错处理 (不再有 2s 的停止服务时间)
- Chunk 大小只有 1MB (对小文件很友好)
- Master 可以存储更多的 Metadata(当 Chunk 从 64MB 变为 1MB 后,Metadata 会扩大 64 倍,但是 Google 也解决了)
Colossus 可以自动分区 Metadata。使用 Reed-Solomon 算法来复制,可以将原先的 3 份减小到 1.5 份,提高写的性能,降低延迟。
至于 Spanner 相对于 BigTable 和 Megastore 的优势,颜开认为:
BigTable 在 Google 得到了广泛的使用,但是它不能提供较为复杂的 Schema,还有在跨数据中心环境下的强一致性。Megastore 有类 RDBMS 的数据模型,同时也支持同步复制,但是它的吞吐量太差,不能适应应用要求。Spanner 不再是类似 BigTable 的版本化 key-value 存储,而是一个“临时多版本”的数据库。何为“临时多版本”,数据是存储在一个版本化的关系表里面,存储的时间数据会根据其提交的时间打上时间戳,应用可以访问到较老的版本,另外老的版本也会被垃圾回收掉。
Google 官方认为 Spanner 是下一代 BigTable,也是 Megastore 的继任者。
颜开提到 Spanner 作为一个全球化分布式系统的有趣特性:
- 应用可以细粒度的指定数据分布的位置。精确的指定数据离用户有多远,可以有效的控制读延迟 (读延迟取决于最近的拷贝)。指定数据拷贝之间有多远,可以控制写的延迟 (写延迟取决于最远的拷贝)。还要数据的复制份数,可以控制数据的可靠性和读性能。(多写几份,可以抵御更大的事故)
- Spanner 还有两个一般分布式数据库不具备的特性:读写的外部一致性,基于时间戳的全局的读一致。这两个特性可以让 Spanner 支持一致的备份,一致的 MapReduce,还有原子的 Schema 修改。
这些特性都得益于 Spanner 的全球时间同步机制:
全球时间同步机制,可以在数据提交的时候给出一个时间戳。因为时间是系列化的,所以才有外部一致性。这个很容易理解,如果有两个提交,一个在 T1, 一个在 T2。那有更晚的时间戳那个提交是正确的。
这个全球时间同步机制是用一个具有 GPS 和原子钟的 TrueTime API 提供了。这个 TrueTime API 能够将不同数据中心的时间偏差缩短在 10ms 内。这个 API 可以提供一个精确的时间,同时给出误差范围。
颜开认为:
这个 TrueTime API 非常有意义,如果能单独开源这部分的话,很多数据库如 MongoDB 都可以从中受益。
颜开接下来分析了 Spanner 的体系结构:
Spanner 由于是全球化的,所以有两个其他分布式数据库没有的概念。
- Universe。一个 Spanner 部署实例称之为一个 Universe。目前全世界有 3 个。一个开发,一个测试,一个线上。因为一个 Universe 就能覆盖全球,不需要多个。
- Zones. 每个 Zone 相当于一个数据中心,一个 Zone 内部物理上必须在一起。而一个数据中心可能有多个 Zone。可以在运行时添加移除 Zone。一个 Zone 可以理解为一个 BigTable 部署实例
其中还包括如下组件:
- Universemaster: 监控这个 universe 里 zone 级别的状态信息
- Placement driver:提供跨区数据迁移时管理功能
- Zonemaster:相当于 BigTable 的 Master。管理 Spanserver 上的数据。
- Location proxy:存储数据的 Location 信息。客户端要先访问他才知道数据在那个 Spanserver 上。
- Spanserver:相当于 BigTable 的 ThunkServer。用于存储数据。
颜开分析了 Spanner 中的抽象概念 directory,它让 Spanner 比 Bigtable 具备更强扩展性:
Directory 是一些 key-value 的集合,一个 directory 里面的 key 有一样的前缀。更妥当的叫法是 bucketing。Directory 是应用控制数据位置的最小单元,可以通过谨慎的选择 Key 的前缀来控制。……Directory 还是记录地理位置的最小单元。
对于 Spanner 的数据模型,颜开的分析是:
在设计之初,Spanner 就决心有以下的特性:
- 支持类似关系数据库的 schema
- Query 语句
- 支持广义上的事务
……
据模型是建立在 directory 和 key-value 模型的抽象之上的。一个应用可以在一个 universe 中建立一个或多个 database,在每个 database 中建立任意的 table。Table 看起来就像关系型数据库的表。有行,有列,还有版本。Query 语句看起来是多了一些扩展的 SQL 语句。
Spanner 的数据模型也不是纯正的关系模型,每一行都必须有一列或多列组件。看起来还是 Key-value。主键组成 Key, 其他的列是 Value。但这样的设计对应用也是很有裨益的,应用可以通过主键来定位到某一行。
对于 Spanner 的并发控制,颜开提到:
Spanner 使用 TrueTime 来控制并发,实现外部一致性。支持以下几种事务。
- 读写事务
- 只读事务
- 快照读,客户端提供时间戳
- 快照读,客户端提供时间范围
那么何时能出现开源的 Spanner 和 F1 产品呢?颜开的分析是:
GFS 出现于 2001 年,Hadoop 出生是在 2007 年。如果 Hadoop 是世界领先水平的话,GFS 比世界领先水平还领先了 6 年。同样的 Spanner 出生大概是 2009 年,现在我们看到了论文,估计 Spanner 在 Google 已经很完善,同时 Google 内部已经有更先进的替代技术在酝酿了。笔者预测,最早在 2015 年才会出现 Spanner 和 F1 的山寨开源产品。
颜开博客上的原文对 Spanner 有更多深入的细节分析,如果读者想了解更多,请移步颜开的这篇博客。
评论