海量存储之十八--一致性和高可用专题

简介: 我们已经在上面的分析中,我们已经看到observer模型在多机场景下的问题,所以,paxos模型的目标就是解决这个问题,他解决这个问题的方法就是quorum模型。 我的目标是让大家能弄明白,掌握这些复杂的概念,所以我也会将以前我在淘宝java中间件团队内分享时候,大家经常犯的一些错误,也写到【】里
我们已经在上面的分析中,我们已经看到observer模型在多机场景下的问题,所以,paxos模型的目标就是解决这个问题,他解决这个问题的方法就是quorum模型。

我的目标是让大家能弄明白,掌握这些复杂的概念,所以我也会将以前我在淘宝java中间件团队内分享时候,大家经常犯的一些错误,也写到【】里面,尽可能让大家少走弯路,如果有什么感想,疑问,后面可以留言。

PS 广告插播 : 淘宝java中间件团队,你值得拥有:)

----PAXOS------

好,我们回顾一下上下文,我们在上篇文章中谈到,当机器变得更多的时候Observer不能只有一个。必须有更多个Observer,但Observer多了,到底听谁的又成了问题。你一言我一语,大家都觉得自己是老大,谁也不服谁。咋办捏?

这时候就得有人站出来,说:那我们少数服从多数吧!制定一套策略,在各种情况下都能够选出一个决议不就行了!

这其实就是paxos协议的核心想法之一,我们来看一下他是怎么做到的。在这里,我不想去做那个繁琐的证明过程,那个过程如果你感兴趣,可以去看paxos made simple这篇文章,有中文,这里给出http://blog.csdn.net/sparkliang/article/details/5740882 ,数星星同学也翻译过。可以直接google.


我在这里只说结论,因为结论更容易理解一些。

我们假定有A,B,C,D,E五台机器。kv系统需要put一个数据[key=Whisper -> val=3306]到我们这5台机器上,要保证只要反馈为真,任意两台机器挂掉都不会丢失数据,并且可以保证高可用。怎么做:

1.首先,客户端随机选择一个节点,进行写入提交,这里我们随机选择了C这个节点,这时候C节点就是这次提议的发起人【也叫proposer,在老的2pc协议里也叫做coodinator】,当C收到这个提议的时候,C首先要做的事情是根据当前节点的最新全局global id,做一次自增操作,我们假定,在当时全局id,Global ID是0,所以,这个议案就被对应了一个编号,1--->[key=Whisper -> val=3306]。

【【这里有两个我们经常犯的错误,下面做一个解说:

1.global id问题,在老的论文里,Lamport没有描述这个自增id是怎么生成的,所以大家的第一个疑问一般是问id怎么生成,从我目前能够看到的所有实现里面,基本上就是选择哪一台机器,就是以那台机器当前所保持的全局id(snapshot,可能不是全局来看的最高值,但没关系,只要是自己这台机器的最高值就行了),然后做一下自增就行了。我们后面会看到协议如何保证非全局最高值的globalID提议会被拒绝以至于不能够形成决议。

2.global id --->[key=Whisper -> val=3306] . 这也是个会让人困惑的问题,在原文中,他被表示为一个key-value的形式,比如proposal[0->value] 。这会让人自然的联想到与数据库的kv相对应,key是0,value是value。然后就会困惑,这个数据是怎么和数据库对应起来的呢?这是我当时的困惑,现在也把他列在这里。其实很简单,这里的global id对应value.global id只是对paxos协议有意义,对于数据库,其实只需要关心value里面的数据即可,也即将global id --->[key=Whisper -> val=3306]里面的value: [key=Whisper-> val=3306] 作为数据库构建映射时所需要的redoLog就行了,global id的作用只是告诉你这些数据的顺序是按照global id来排列的,其他无意义。 】】


我们回到文中,我们已经将这个新的议案标记了从C这台机器看起来最大的global id : 1--->[key=Whisper -> val=3306]。然后,他会尝试将这个信息发送给其余的A,B,D,E这几台机器。

我们来看这些机器的操作流程。 在这个过程中,Paxos将A,B,D,E叫做accepter【老的协议里没有区分,管这些都叫做参与者,cohorts】,他们的行为模式如下:

如果A,B,D,E这几台机器的globalID 小于C给出的决议的GID(1--->[key=Whisper -> val=3306]),那么就告诉C,这个决议被批准了。而如果A,B,D,E这几台机器的GlobalID 大于或等于C给出决议的GID.那么就告知C 这个决议不能够被批准。

我们假定A,B两台机器当时的Max(GID)是0 ,而D,E的Max(GID)是1.那么,A,B两台机器会反馈给C说协议被接受,这时候我们算算,C的议案有几票了?A B !C!,一定要算自己哦:) 。所以,这个议案有三票,5台机器的半数是3.超过法定人数,于是决议就被同意了。



我们保持这个上下文,来看看D,E这边的情况。首先,要思考的问题是,为什么D,E的Max(GID)是1呢?

其实很简单,D可能在C发起决议的同时,也发起了一个决议,我们假定这个决议是由D发起的,决议是 1--->[key=taobao ->val=1234]。既然D,E的Max(GID)是1,那么意味着E已经告知D,它同意了他的决议,但D马上会发现,A,B,C里面的任意一个都返回了D不同意。他的议案只拿到两票,没有通过,它虽然有点不爽,但也是没办法的事情啊。。

这时候C的决议已经被多数派接受,所以他需要告知所有人,我的议案1--->[key=Whisper -> val=3306]已经被接受,你们去学习吧。




这时候还有一个问题是需要被考虑的,如果在C已经得知决议已经达到法定人数,在告知所有人接受之前,C挂了,应该怎么办呢?

我之所以没有将这个放到开始的描述里,主要原因是觉得这是个独立因素,不应该影响议案被接受时候的清晰度。

为了解决这个问题,需要要求所有的accepter在接受某个人提出的议案之后,额外的记录一个信息:当前accepter接受了哪个提议者的议案。


为什么要记录这个?很简单,我们看一下上面出现这个情况时候的判断标准。

A 机器:角色-accepter 。 批准的议案 1--->[key=Whisper-> val=3306] 。提议人:C

B 机器:角色-accepter 。 批准的议案 1--->[key=Whisper-> val=3306] 。提议人:C

C机器:角色-proposer 。 挂了。。不知道他的情况。

D 机器:角色-accepter 。 批准的议案 1--->[key=taobao->val=1234] 。提议人:自己

E 机器:角色-proposer。 “提议的”议案 1--->[key=taobao->val=1234] 。提议人:D。

因为有了提议人这个记录,所以在超时后很容易可以判断,议案1--->[key=Whisper -> val=3306] 是取得了多数派的议案,因为虽然D,E两台机器也是可以达成一致的议案的。但因为有个人本身是提议者,所以可以算出这个议案是少数派。

就可以知道哪一个议案应该是被接受的了。



在这之后,提议者还需要做一件事,就是告知D,E,被决定的决议已经是什么了。即可。

这个过程在文章中叫Learn. D,E被称为Learner.

别看写的简单,这个过程也是变数最大的过程,有不少方法可以减少网络传输的量,不过不在这里讨论了。




下面,我们讨论一下我们在2pc/3pc中面临的问题,在paxos里面是怎么被解决的。

2pc最主要的问题是脑裂,死等。两个问题。

对于脑裂,paxos给出的解决方案是,少数服从多数,决议发给所有人,尽一切努力送达,总有一个决议会得到多数派肯定,所以,不在纠结于某一台机器的反馈,网络无响应?没有就没有吧,其他人有反馈就行了。

所以,如果出现了机房隔离的情况,比如A,B,C在机房1,D,E在机房2,机房1和机房2物理隔离了,那么你会发现,D,E永远也不可能提出能够得到多数派同意的提案。

所以,少数派的利益被牺牲了。。换来了多数派的可用性。我们分析过,这是唯一能够既保证数据的一致性,又尽可能提高可用性的唯一方法。

而对于死等问题,解决的方法也是一样的,对于某一台机器的无响应,完全不用去管,其他机器有相应就行了,只要能拿到多数,就不怕一小撮别有用心的反对派的反攻倒算~。



---------------------------------paxos就是这样一个协议----------

休息一下

----------------------------------------------------------------------------------------




那么Paxos有没有什么值得改进的地方?有的,很简单,你会发现,如果在一个决议提议的过程中,其他决议会被否决,否决本身意味着更多的网络io,意味着更多的冲突,这些冲突都是需要额外的开销的,代价很大很大。

为了解决类似的问题,所以才会有zoo keeper对paxos协议的改进。zk的协议叫zab协议,你可以说zab协议不是paxos,但又可以说是paxos.但将paxos和zab协议之间做直接的等同关系,无疑是【错误】的。

其实,这也是在我们的现实生活中经常能够发现的,如果每个议案都要经过议会的讨论和表决,那么这个国家的决策无疑是低效的,怎么解决这个问题呢?弄个总统就行了。zab协议就是本着这个思路来改进paxos协议的。



---------paxos 改进----zab协议讨论-----------------

zab协议把整个过程分为两个部分,第一个部分叫选总统,第二个部分叫进行决议。

选总统的过程比较特殊,这种模式,相对的给人感觉思路来源于lamport的面包房算法,这个我们后面讲。,选择的主要依据是:

1.如果有gid最大的机器,那么他是主机。

2.如果好几台主机的gid相同,那么按照序号选择最小的那个。

所以,在开始的时候,给A,B,C,D,E进行编号,0,1,2,3,4。 第一轮的时候,因为大家的Max(gid)都是0,所以自然而然按照第二个规则,选择A作为主机。

然后,所有人都知道A是主机以后,无论谁收到的请求,都直接转发给A,由A机器去做后续的分发,这个分发的过程,我们叫进行决议。

进行决议的规则就简单很多了,对其他机器进行3pc 提交,但与3pc不同的是,因为是群发议案给所有其他机器,所以一个机器无反馈对大局是没有影响的,只有当在一段时间以后,超过半数没有反馈,才是有问题的时候,这时候要做的事情是,重新选择总统。

具体过程是,A会将决议precommit给B,C,D,E。然后等待,当B,C,D,E里面的任意两个返回收到后,就可以进行doCommit().否则进行doAbort().

为什么要任意两个?原因其实也是一样的,为了防止脑裂,原则上只能大于半数,不能少于半数,因为一旦决议成立的投票数少于半数,那么就存在另立中央的可能,两个总统可不是闹着玩的。

定两个,就能够保证,任意“两台”机器挂掉,数据不丢:),能够做到quorum。。

然后是我的个人评述,写zab协议的人否认自己的协议是paxos.变种 其实我也是有些认同的。不过,他们是针对一个问题的两种解决方法:

因为他们解决的问题的领域相同

解决网络传输无响应这个问题的方法也一样:也即不在乎一城一池的得失,尽一切努力传递给其他人,然后用少数服从多数的方式,要求网络隔离或自己挂掉的机器,在恢复可用以后,从其他主机那里学习和领会先进经验。

并且也都使用了quorum方式来防止脑裂的情况。

核心思路是类似的,但解决问题的方法完全是两套。 paxos在其他公司的实现里面也对paxos进行了这样,那样的改进。不过核心思路都是这个。


我们对paxos协议的讲解,就到这里。

也留下一个问题,zab协议,如果我们用在google 全球数据库spanner上,会不会有什么问题呢?请大家思考哈 :)

后记,抱歉,这篇文章一个图都没有。。我已经尽可能用简单的方式来描述paxos和他的变种协议了(当然有一个作为了问题)。如果有哪个地方不明白,也还请在后面留言吧。友情提示这篇文章不适于跳跃性阅读,想要理解,必须从第一行开始读到最后。。。。

google的工程师说,所有的一致性协议都是paxos的特例,我表示不置可否吧。。。。下一篇我们要讨论另外一系的实现,gossip模型的实现。我个人感觉:把gossip归类到paxos模型,似乎也不是很合适。gossip协议的两个主要的实现方式,是dynamo和cassandra.我们在下一篇里面进行讨论


该文章转载自: 淘宝沈询_WhisperXD的博客
目录
相关文章
|
1月前
|
存储 关系型数据库 OLAP
TiDB适用场景解析:海量数据存储与高并发读写的利器
【2月更文挑战第25天】随着大数据时代的到来,海量数据存储和高并发读写成为众多企业面临的挑战。TiDB作为一种高性能、分布式的关系型数据库,以其独特的架构和强大的功能,在多个场景中展现出了卓越的性能。本文将详细探讨TiDB在海量数据存储、高并发读写等场景下的适用情况,分析其在不同业务场景中的优势与应用价值。
|
7月前
|
消息中间件 算法 NoSQL
硬核!万字神文精解高并发高可用系统实战,分布式系统一致性文档
本文专注于分布式系统的一致性,从实例、算法、原理多方面深入浅出地讲解其中的奥妙。架构的终极奥义正是化繁为简,非精深者不能为之。 对于有志于钻研技术架构、扩展行业视野的同道中人,相信本文会带给你很多思考和成长。比如:
|
11月前
|
存储 运维 网络协议
带你读《存储漫谈:Ceph原理与实践》——1.1.1 集中式存储系统
带你读《存储漫谈:Ceph原理与实践》——1.1.1 集中式存储系统
|
存储 SQL NoSQL
高性能分布式No SQL数据库Aerospike(四)——经验总结和最佳实践
高性能分布式No SQL数据库Aerospike(四)——经验总结和最佳实践
302 0
|
存储 消息中间件 缓存
分布式系统中数据存储方案实践
在项目研发的过程中,对于数据存储能力的依赖无处不在,项目初期,相比系统层面的组件选型与框架设计,由于数据体量不大,在存储管理方面通常容易被轻视,当项目发展进入到中后期阶段,系统的复杂性很大程度来源于数据层面;
230 0
分布式系统中数据存储方案实践
|
存储 缓存 分布式计算
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.2各主流分布式方案对比(一)
《存储漫谈Ceph原理与实践》第一章分布式存储概述1.2各主流分布式方案对比
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.2各主流分布式方案对比(一)
|
存储 算法 关系型数据库
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.2各主流分布式方案对比(二)
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.2各主流分布式方案对比
 带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.2各主流分布式方案对比(二)
|
存储 运维 负载均衡
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.1存储系统的架构演进(一)
《存储漫谈Ceph原理与实践》第一章分布式存储概述1.1存储系统的架构演进…
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.1存储系统的架构演进(一)
|
存储 缓存 大数据
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.1存储系统的架构演进(二)
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.1存储系统的架构演进
带你读《存储漫谈Ceph原理与实践》第一章分布式存储概述1.1存储系统的架构演进(二)