关闭

Google Megastore读写的架构分析

标签: google算法优化jsonmysqlup
6269人阅读 评论(0) 收藏 举报
分类:

使用在什么地方?

google的megastore早在今年2月份公开后,马上就国人翻译了它,但我个人看了翻译似乎还是不怎么理解,还是看看E文的吧,这篇文章的原文直接用google搜索“google megastore” ,基本前面几条就有这篇文章了。我个人感觉,他这篇文章的主要使用之处,是对于多机房的使用,即在不同的地域之间使用paxos算法来达到数据的强一致,相对于国内多机房的数据同步,大多数公司使用mysql的slave方式来说,应该是有一定的借鉴意义的,而对于同一机房,使用master-slave和zookeeper的监控就完全足够了。


设计是怎么样的?

说完了它的使用之处后,再说说它的设计是怎么样的。显然,它最核心的部分应该是读写日志的部分了,使用了multi-paxos的算法,再加上一些优化(本地读,fast-write,multi-paxos的预分配快速写得方式),这样便构成了megastore的多机房的读写架构,后边详细讲这个读写这两块功能。当然,还需要包括一些节点失败恢复到最新状态和分区容忍(任何隔离一个机房,依然是保证数据是一致的或者不可用)的设计。


在设计过程中,google是怎么选leader的?提交数据最频繁的地方的replica作为一个leader,并且每个leader都有一个lease(租期),用完了lease再重新选择leader。对于写日志位置的话,megastore允许replicas接受out-of-order(无序)的建议,即写日志不需要按找顺序写,可以先写日志位置为101,再写日志位置为100。

  a.读设计


        读的过程图

   这里看到了Coordinator(协调器),就先说说这个Coordinator是干什么的,它其实做的事情很少:

        1). 告诉客户端本地的replica数据是不是最新的状态

        2). 如果replica(副本)没有accept(接受)写入到某一个entity group(有点类似json数据),那么Coordinator就移除这个key(commited 之前)

        3). catch up(更新)好后,让Coordinator写入这个key


    如果是current read(当前读)的过程是这样的,首先,查看本地的Coordinator,看看本地的replica是不是最新的,

        1). 如果是最新,则从本地的replica查找并读取已经接受的最大的日志位置号和时间戳

        2). 如果不是最新的,则发起一个大多数读的操作,从其他的replicas找到一个最大日志号位置,并选择一个replica,并通过该replica更新本地的replica到最新的状态;如                果这个值,该replica也无法确定是一致的,则从其他的replica读取该位置的值;如果对于一些日志位置没有包含一个已commited的值,则使用paxos发起一个no-op的                写,则最终会收敛于该某个值,我在想似乎所有的有缺少的值都可以使用paoxs发起一个no-op的写,最终都会收敛于某个值,只是这样可能代价太大点。然后,让                       Coordinator写入这个group的key

    通过,这样的操作后,使用这个log位置的时间戳从本地的replica读数据,读数据的结果可能会是多个replicas的汇聚起来的结果,这个似乎有点让人费解,读数据还需要到多个地方去读的!但,如果,本地的replica不行的话,(可以让它catch up it)就另外选择一个。


b. 写设计


        写的过程图

    在写之前,megastore要先知道下一个未使用的日志位置,和最后一次写得时间戳,以及是leader replica,由于要读取日志位置和时间戳,所以对于第一次的写过程还是需要像read那样,获得日志位置,时间戳,但是这个leader对于当前的客户端是怎么知道的,似乎没有说清楚,我在想应该是每个replica都知道才对,这个获得日志位置的同时,其实leader也知道了。

    一开始就以建议号为0发送给leader一个写的命令让其接受写在n的位置(跳过了prepare阶段),leader直接将值写在n+1的日志位置,

        1).  如果成功,则直接写入,并且让其他的replicas也在这个位置apply,如果在apply的时候不成功,则跳至下面 2)

         2). 如果不成功,则需要进行一个两阶段的paxos的算法,先prepare所有的replicas(当然,包括了leader本身),然后收到,如果超过一半接受,则发送一个accept,请求所有的replicas接受

    这里解释一下这个建议号为0,multi-paxos的一个优化是,如果上一次写成功了,则下一次写使用上一次写的一个预分配号n+1,不用再进行一次prepare阶段,而直接提交accept,但是这里和multi-paxos似乎有写区别,它是一开始就直接提交给leader,leader一接受,则其他的也replicas也跟着接受。

    这里在写入的时候似乎有点问题,如果在leader被写入,但是其他apply没有成功的时候怎么办?论文上,是这么说的,执行paxos算法后把值给替换了;那么这时候会不会有用户读取该数据会不一致呢?论文上说了,必须是让所有的Coorninators都更新了,数据才达到visibility(可见)点。

    

有问题,非常欢迎指正!

也可以直接与我(微博)讨论

2
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:204296次
    • 积分:1773
    • 等级:
    • 排名:千里之外
    • 原创:30篇
    • 转载:3篇
    • 译文:1篇
    • 评论:83条
    文章分类
    最新评论