有一个由 2 个节点组成的分布式系统来存储数据。数据被复制到两个节点,这样如果一个节点死亡,数据不会丢失(持久性)并继续提供服务(可用性)。您还希望您的 2 节点系统每秒处理两倍的请求(可扩展性)。
假设对单个键的写入可以到达任何节点。你的客户写“1”作为某个键的值,then它决定写“2”。第一次写入到节点#1。它向节点#2 发出复制请求。但是,您存储“2”的请求比复制请求更早到达节点#2(记住,我们可以存储在任何节点上)。它存储“2”,向节点#1发出带有“2”的复制请求,从它接收带有“1”的复制请求,将其“2”更改为“1”,而节点#1将其“1”更改为“2”。现在,存储节点之间的数据不一致。另外,如果节点#1 死亡,您所拥有的只是值为“1”的节点#2,而您清楚地记得您发送了“2”after“1”,存储系统已确认保存。实际上,很多事情可能会出现“错误”,具体取决于您对存储系统的期望(读取写入?单调读取?等),因此您需要一种方法来真正找出键的真实、良好、实际值是,甚至是为了防止系统以这种方式“破坏”数据。为此,存储系统需要知道在其节点之间发生了什么,或者甚至可能包括您的客户对事件顺序的看法。矢量时钟 https://en.wikipedia.org/wiki/Vector_clock and 版本向量 https://en.wikipedia.org/wiki/Version_vector是实践中用于实现这一目标的一些技术,或者声称两个事件同时发生,并且您需要一些其他方法来在它们的结果之间做出决定。
您决定以不同的方式解决该问题,以避免所有这些复杂性:某个键的所有写入都将转到一个节点(称为“领导者”),并将这些写入复制到另一个节点。事实上,这看起来是一种更简单的方案:在一个节点(可能还有一个进程)内,您拥有快速且经过验证的并发控制技术,可以轻松地对事件进行排序,可以以相同的顺序应用复制;此外,总有正确数据的权威来源。唯一的问题是您的 2 个存储节点需要就特定密钥的领导者达成一致。如果您有 3 个节点,其中一个节点死亡,那么另外 2 个节点需要决定 1)它们都认为旧领导者已死亡,2)其中哪一个是新领导者。为此,存在共识协议(Paxos https://en.wikipedia.org/wiki/Paxos_(computer_science), 2阶段提交 https://en.wikipedia.org/wiki/Two-phase_commit_protocol, Raft https://raft.github.io/、Zab、三阶段提交等)。
为什么不总是选择单一领导者(因此是共识协议)而不是无领导者方案(因此是像版本向量这样的排序机制)?谈判领导权需要时间(最多几秒或几十秒),在此期间您的系统在某些特殊模式下不可用或部分可用。无领导者在某些其他条件下也可以表现得更好(例如,领导者由于软件问题或网络问题而变得缓慢:使用无领导者方法,其他节点可能会接管其职责)。随着参与者数量的增加,达成共识变得更加困难,因此无领导者可能会更好地扩展。
最后,让我们逐字逐句地回答您的问题:
我会在什么样的系统中使用矢量时钟之类的东西?
您可能希望将版本向量用于无领导者分布式存储。您可以使用矢量时钟来实现相同的目的(尽管它是更不适合 https://haslab.wordpress.com/2011/07/08/version-vectors-are-not-vector-clocks/;该文章还建议您使用它来获得一致的快照,以实现因果顺序 https://en.wikipedia.org/wiki/Causal_consistency在一般分布式系统等)。
哪个系统最适合使用 Paxos 之类的东西?
单领导者或多领导者分布式存储。很少更新的数据(想想配置)、集群参与信息的数据库——如果这些信息很关键,否则八卦会更好地扩展。分布式锁。
两者是互相排斥的吗?
不会。两者都可以用于解决相同的任务(例如分布式存储)。它们可以组合起来(用于集群参与的 paxos,然后使用该知识来确定哪些节点在最终一致(通过版本向量)系统中形成仲裁)。