Paxos
发展史
Leslie Lamport所提出的Paxos算法是现代分布式系统中的一项重要的基础性技术,得到广泛的应用。
Paxos的整个发展过程大概可以分为三个阶段:
第一阶段:萌芽期,大致是1988-1996年。Liskov等人在PODC上发表了Viewstamped Replication: A New Primary Copy Method to Support Highly-Available Distributed Systems ,提出了一个在副本出现宕机情况下仍能正常工作的主从备份算法,该算法与Paxos在本质上是一致的(The ABCD’s of Paxos)。
第二阶段:1996-2007年。涌现出一批Paxos的不同版本,这些Paxos的变种从不同侧面完善了基础Paxos算法,提升其性能。Liskov等人在1999年提出了PBFT(实用的拜占庭容错算法),这实际上也是Paxos的一个变种,被Lampson称为Byzantine Paxos,该算法对基础Paxos进行了改进,使其可以处理拜占庭错误。
拜占庭将军问题(Byzantine failures),是由莱斯利·兰伯特提出的点对点通信中的基本问题。含义是在存在消息丢失的不可靠信道上试图通过消息传递的方式达到一致性是不可能的。
拜占庭位于如今的土耳其的伊斯坦布尔,是东罗马帝国的首都。由于当时拜占庭罗马帝国国土辽阔,为了防御目的,因此每个军队都分隔很远,将军与将军之间只能靠信差传消息。 在战争的时候,拜占庭军队内所有将军和副官必需达成一致的共识,决定是否有赢的机会才去攻打敌人的阵营。但是,在军队内有可能存有叛徒和敌军的间谍,左右将军们的决定又扰乱整体军队的秩序。在进行共识时,结果并不代表大多数人的意见。这时候,在已知有成员谋反的情况下,其余忠诚的将军在不受叛徒的影响下如何达成一致的协议,拜占庭问题就此形成。
拜占庭假设是对现实世界的模型化,由于硬件错误、网络拥塞或断开以及遭到恶意攻击,计算机和网络可能出现不可预料的行为。拜占庭容错协议必须处理这些失效,并且这些协议还要满足所要解决的问题要求的规范。
Eli Gafni 和 Lamport 在2000年提出了Disk Paxos,这可以认为是Paxos基于磁盘的版本,以支持持久化。
第三阶段:本阶段。Paxos开始在工业界得到了广泛应用。从2006年开始,谷歌公司有两篇影响深远的论文发表在OSDI上,一篇是“Bigtable:A Distributed Storage System for Structured Data”,另一篇“The Chubby lock service for loosely-coupled distributed systems”。两篇论文可以说是揭开了大数据管理的序幕,而Paxos则在大数据管理的核心技术(容错)中扮演了极为重要的角色。
算法原理
Paxos算法维基百科https://en.wikipedia.org/wiki/Paxos_(computer_science)
Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。然而,Paxos算法也因为晦涩难懂而臭名昭著。
问题产生的背景
在常见的分布式系统中,总会发生诸如机器宕机或网络异常(包括消息的延迟、丢失、重复、乱序,还有网络分区)等情况。Paxos算法需要解决的问题就是如何在一个可能发生上述异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性。
相关概念
在Paxos算法中,有四种角色:
- Client:产生议题者
- Proposer :提议者
- Acceptor(Voters):决策者(投票者)
- Learner:最终决策学习者,也就是执行者。
上面4种角色中,提议者和决策者是很重要的,其他的2个角色在整个算法中应该算做打酱油的,Proposer就像Client的使者,由Proposer使者拿着Client的议题去向Acceptor提议,让Acceptor来决策。
- Proposer拿着Client的议题去向Acceptor提议,让Acceptor来决策。
- Proposer提出议题,Acceptor初步接受或者Acceptor初步不接受。
- Acceptor初步接受则Proposer再次向Acceptor确认是否最终接受。
- Acceptor最终接受或者Acceptor最终不接受。
- Learner最终学习的目标是向所有Acceptor学习,如果有多数派个Acceptor最终接受了某提议,那就得到了最终的结果,算法的目的就达到了。
问题描述
假设有一组可以提出(propose)value(value在提案Proposal里)的进程集合。一个一致性算法需要保证提出的这么多value中,只有一个value被选定(chosen)。如果没有value被提出,就不应该有value被选定。如果一个value被选定,那么所有进程都应该能学习(learn)到这个被选定的value。对于一致性算法,安全性(safaty)要求如下:
- 只有被提出的value才能被选定。
- 只有一个value被选定,并且
- 如果某个进程认为某个value被选定了,那么这个value必须是真的被选定的那个。
Paxos的目标:保证最终有一个value会被选定,当value被选定后,进程最终也能获取到被选定的value。
算法描述
Paxos算法分为两个阶段。具体如下:
阶段一:
(a) Proposer选择一个提案编号N,然后向半数以上的Acceptor发送编号为N的Prepare请求。
(b) 如果一个Acceptor收到一个编号为N的Prepare请求,且N大于该Acceptor已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号最大的提案(如果有的话)作为响应反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案。
阶段二:
(a) 如果Proposer收到半数以上Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对[N,V]提案的Accept请求给半数以上的Acceptor。注意:V就是收到的响应中编号最大的提案的value,如果响应中不包含任何提案,那么V就由Proposer自己决定。
(b) 如果Acceptor收到一个针对编号为N的提案的Accept请求,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案。
eg.
Learner学习被选定的value
Learner学习(获取)被选定的value有如下三种方案: