note: Spanner: Google’s Globally-Distributed Database

时间:2014-05-08 06:46:57   收藏:0   阅读:640

1. Abstract & introduction

ref:http://static.googleusercontent.com/media/research.google.com/zh-CN//archive/spanner-osdi2012.pdf

Spanner是google为了弥补bigtable的不足而推出的新一代的数据库系统。首先,看看bigtable有哪些不足。
     看这篇文章前应该看看bigtable的文章http://www.cnblogs.com/zwCHAN/p/3698191.html

另外,对于Gmail、Calendar、Android market、AppEngine这几个我平时用的应用时在Megastore上运行的表示极为惊讶。。

所以,Spanner的设计目标是集传统关系数据库和k-v模型数据库的优势于一体,支持可扩展、多版本、全球分布式、全局同步复制的半关系话数据库。为了支持这些特性,它提出了TrueTime的概念,使用了paxos同步算法、只读事务无锁化处理等方法;设计了一套类似Megastore的sql语言;为了支持全球范围的分布式数据库(同步复制)功能,spanner有几个功能很有启发性,

2 Implementation:

2.1 spanner的逻辑结构:

  bubuko.com,布布扣

2.2 软件架构

bubuko.com,布布扣

3. TrueTime

truetime的概念在spanner中非常重要,但却没有说怎么实现的。说在另一篇论文说明,但没找到。truetime的api:

bubuko.com,布布扣

TT.now()这样的接口在平时的api中会返回一个确切的时间,但这里返回的是一个时间范围,它表示,调用TT.now的真实时间,肯定在返回值得时间范围内。其实这也很好理解,因为如果在一台机器上,要确定一个时间是很简单的,获取当前时钟就可以了;但是如果想在同一绝对时间内(绝对时间是指不依赖于计算机时钟系统的客观时间)在所以机器上调用TT.now,都要得到一个相同的返回值,这就要求所以机器的时钟系统是完全一致的。这其实是不可能做到的事情(参见http://www.cnblogs.com/zwCHAN/p/3652948.html),假设所有机器的时间差(最慢的时钟减去最快的时钟的差为e,那么在任何一台机器上调用TT.now,都可以确定此时的真实时间范围是(-e+TT.now, e+TT.now). 如下图,完美的钟指示着绝对时间,而在绝对时间的9:00:00后每隔10s,同时在三台server上调用获取now时间,他们得到的值不同,误差为7s。所以当一个人不知道绝对时间,但直到这个误差为7s,在server1上调用now,得到9:00:08这个时间点,他就可以肯定当前真实时间在(9:00:01,9:00:15)之间(时钟频率的偏差都在10**-6以下,可忽略)。

而事实上,获取误差e的准确值也是不可能(和时钟同步一个道理),只能确定某个e’,且e’>=e, 这样,我们就相当于取个“安全值”。例如这个例子中取个10s误差,那肯定也是正确的。同时也说明,server之间的误差越小,我们能得到的e’也就越小。

bubuko.com,布布扣

paper中说谷歌使用的是GPS时钟同步,可以使e降低为10ms以内;而他们的目标是1ms。。。 truetime的误差对系统的影响也是赤裸裸的:在这个误差范围内,只能有一个事务执行

4. Concurrency control

在spanner系统中,只有读写事务操作使用了悲观锁机制,其他操作都是无锁的。spanner依赖于分配给各个事务的时间戳的单调递增性,也就是需要确保事务的有序性。

对于读写事务操作,站在软件架构最高位置的coordinator leader再给一个写事务分配时间戳Si时,确保Si不小于TT.now().latest,也就是这个时间戳肯定在其他所有参与事务的机器上的事务的时间戳都大,当每个事务都这样操作时,就能确保时间戳是单调递增的(当然,为了满足这个条件,coordinator可能要等待。

分析一个完整的读写事务的过程:client的一个事务要求要读取group1、group2、group3的值后更新。图中的数字标识步骤。了解了最复杂的读写事务,其他事务就很容易了。

bubuko.com,布布扣

  1. client通知leader replica获取读锁read-lock;
  2. client read last-update data on a replica;
  3. client write all to the buffer
  4. client选择一个coordinator group, 然后开始发起一个2PC提交写的内容;
  5. client将选择到的coordinator标识+buffer write 发送给所有的paticipant leader;(从而避免发给coordiantor,然后coordinator再发给participant,在这点上对事务成功是乐观的);
  6. 每个non-coordinator-participant leader(也就是不是coordinator的paxos group的leader)都在本组内获取wirte-lock,然后选取一个比本组内所有之前提出的事务时间戳都大的时间戳,再写入一个prepare paxos log;
  7. 然后non-coordinator-participant leader将选出的时间戳发给coordinator。(至此2PC的Prepare阶段完成)
  8. coordnator自己也在本地获取write-lock,(显然它不用做prepare阶段的事了,client帮它发了)。然后coordinator等待所有的participant learder发过来的时间戳(第7步),选取一个最大值Pmax;
  9. coordinator获取TT.now(),并比较TT.now().latest与Pmax。如果TT.now().laster>=Pmax(标识此时TT.now()为s), 继续往下执行; 否则重复第9步。(这步取保了事务时间戳的单调递增);
  10. coordinator commit一个log到paxos状态机(标识commit事务);
  11. 由于coordinator 提交了commit到paxos状态机,其他的participant就知道事务已经提交了(但不知道coordnator选择的提交的时间戳等详情)。但其他需要同步的Replica还不能马上得到数据,coordinator需要等到after( s)之后才允许同步。这是为了等待前面提到的2倍误差时间过去,确保这个时间戳(时间段)真的过去了(目前为止,所有锁都没释放),然后coordinator开始通知所有的participant和client事务提交的时间戳与事务结果状态;
  12. 每个participant将事务的结果状态提交到自己的paxos group中;
  13. 所有的参与者在得到事务的结果状态和时间戳后,释放锁资源;

5.Evaluation

bubuko.com,布布扣

上图表明,随着replicas的增加,snapshot效率是线性增长的(lock-free),事务写吞吐量会降低,延时变化不大(获取锁效率高)。

bubuko.com,布布扣

上图是2PC的可扩展性性能指标。在50个节点左右,性能恶化不明显。大于100后恶化明显;

bubuko.com,布布扣

上图是google使用GPS时钟同步后,能做到的时钟误差e,基本都在10ms以内;所以它的写事务延时在10ms+;

bubuko.com,布布扣

上图是spanner实际应用中24h平局延时和偏差。(跨美国东西海岸)。可见结果也不容乐观。

note: Spanner: Google’s Globally-Distributed Database,布布扣,bubuko.com

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!