-
主/备服务器
- 例如糟糕的情况:
- put(x, 99) 到达主服务器
- 接着立即进行 get(x)
- 在主服务器获得备份对 put(x,99) 的响应之前
- 我们说主服务器可以在不与备份通信的情况下提供读取服务
- 但是返回 99 并不安全!
- 答案:要么回复旧值,要么阻塞读取,直到所有备份响应 put(x,99)。
- 强制一致
- 新的主服务器可以合并所有副本的最后几个操作。
- 或者,选举为主服务器那个收到最高操作数的备份。
- 新的主服务器必须通过强制备份同意它的方式开始。
- 如何防止备份在与主服务器分离的情况下接管?而且主服务器仍然存活。
- 不要让备份做出这个决定! 只有 CFG 可以宣布新的主服务器 + 备份。
- 这基于 CFG 对它可以到达哪些服务器的看法。
- 如果旧的主服务器实际上是活动的,但 CFG 无法与其通信怎么办?如何防止旧的主服务器提供服务?
- 对于更新:
- 旧的主服务器在所有配置中的副本回复之前不能响应客户端请求
- 至少一个副本必须是新配置的一部分
- 因此副本必须小心,不要回复给旧的主服务器!
- 对于读取:
- 主服务器对于读取不必与备份通信
- 因此 CFG 必须向主服务器授予租约。
- 对于更新:
- 例如糟糕的情况:
-
链式复制旨在解决哪些 p/b 问题?
- 主服务器需要做大量工作
- 主服务器必须发送大量网络数据
- 主服务器故障后重新同步很复杂,因为备份可能不同
-
基本的链式复制思想:
- [客户端,S1=头部,S2,S3=尾部,CFG(=主服务器)] (可以有更多的副本)
- 客户端向头部发送更新请求
- 头部选择顺序(分配序列号)
- 头部更新本地副本,发送到 S1
- S1 更新本地副本,发送到 S2
- S2 更新本地副本,发送到 S3
- S3 更新本地副本,发送响应给客户端
- 更新按顺序沿着链移动: 在每个服务器上,较早的更新在较晚的更新之前交付
- 客户端向尾部发送读取请求,尾部读取本地副本并回复给客户端
-
如果头部发生故障会怎么样?
- CFG(主服务器)负责从故障中恢复。
- CFG通知第二个链式服务器成为新的头部,并告诉客户端新的头部是谁。
- 所有(剩余的)服务器是否仍然是完全相同的副本?
- 它们将很快变得相同!
- 有序交付意味着每个服务器与前一个服务器相同,只是缺少最后几次更新。
- 因此,每个服务器需要与其后继者比较记录,并仅发送那些最后几次更新。
- 一些客户端更新请求可能会丢失
- 如果只有故障的头部知道它们
- 客户端将不会收到响应
- 并最终会重新发送给新的头部。
-
如果尾部发生故障会怎样?
- CFG通知倒数第二个服务器成为新的尾部,并告诉客户端有关读取请求的信息。
- 倒数第二个服务器至少与旧尾部同步。
- 对于新尾部接收但旧尾部未接收的更新,系统不会向客户端发送响应。
- 客户端将超时并重新发送请求。
- 第2节中指出客户端负责检查超时的操作是否实际上已经执行(这通常比听起来更困难)。
-
如果中间服务器发生故障怎么办?
- CFG通知前后服务器进行通信。
- 前一个服务器可能需要重新发送一些已经发送给故障服务器的更新。
请注意,服务器需要在转发后记住更新,以防需要重新发送。
- 何时释放内存?
- 尾部在接收更新时沿着链向上发送确认(ACK)。
- 当服务器收到确认时,它可以释放该操作之前的所有内存。
-
如何添加新服务器?(“扩展链”)需要在发生故障后恢复复制级别时执行此操作。
-
CFG管理这个过程。 新服务器添加在尾部。
-
一种较慢的方法:
- 告诉旧尾部停止处理更新
- 告诉旧尾部将其数据的完整副本发送到新尾部
- 告诉旧尾部开始充当中间服务器,将更新转发到新尾部
- 告诉新尾部开始充当尾部
- 告诉客户端有关新尾部的信息
- 较慢,因为我们需要暂停所有更新数分钟或数小时
-
更好的方法是提前传输状态的快照,然后冻结系统的时间足够长,以发送最后几个更新到新尾部,然后重新配置并解冻,可能使用ZooKeeper的模糊快照概念
-
分区情况与主/备份相似
- CFG做出所有决策
- 它将选择单个新的头部等
- 基于其对服务器活动性的视图——即CFG的分区中的服务器
- 新头部是旧的第二个服务器,它应该忽略来自旧头部的更新,以应对“旧头部仍然存活,但CFG认为它已经故障”的情况
- CFG需要授予尾部提供客户端读取服务的租约,并且在租约到期之前不指定新尾部。
-
-
主/备份(p/b)与链式复制的对比:
- 延迟:
- 主/备份系统可能具有较低的延迟(对于小请求而言)。
- 网络负载:
- 链式复制的头部相较于主服务器具有较低的网络负载。
- 对于大数据项(如GFS),这一点非常重要。
- 任务分配:
- 链式复制将工作分配给头部和尾部,而主/备份系统中主服务器负责所有工作,这可能导致更大的瓶颈。
- 故障恢复:
- 在链式复制中,如果头部失败,确定哪个服务器应该接管以及如何确保服务器重新同步的过程相对简单。
- 延迟:
-
链式复制(或主/备份)与Raft/Paxos/Zab(法定人数)的对比:
- 容错性:
- 链式复制系统可以容忍N个中的N-1个故障,而Raft/Paxos/Zab系统只能容忍N个中的N/2个故障。
- 简单性和速度:
- 链式复制系统可能更简单,也许比Raft/Paxos/Zab系统更快。
- 配置管理:
- 链式复制系统需要一个单独的配置服务(CFG),而Raft/Paxos/Zab系统是自包含的。
- 故障后的处理:
- 链式复制系统在故障后需要等待重新配置,而Raft/Paxos/Zab系统可以继续运行。
- 对慢速节点的容忍性:
- 链式复制系统如果有一个服务器变慢,整个系统可能变慢,而Raft/Paxos/Zab系统可以容忍暂时的慢速节点。
- 故障检测器调优:
- 链式复制系统中,CFG的服务器故障检测器难以调整:任何一个故障的服务器都会阻塞链式复制系统,因此希望尽快宣告故障!但是过于急切的故障检测器会浪费时间将数据复制到新服务器。Raft/Paxos/Zab系统对于短暂/不明确的故障处理更为优雅。
- 长时间以来,主/备份系统(以及链式复制)主导了数据复制领域。Paxos 被认为对于高性能数据库而言过于复杂和缓慢。最近,由于Raft/Paxos/Zab系统对于暂时慢速或不稳定的副本具有良好的容忍性,这些系统开始崭露头角。
- 容错性:
-
在一个大规模的分片设置中,如何布置服务器上的链式复制?这个问题在论文的第5.2、5.3和5.4节中进行了讨论。
一个不太理想的链式复制或主/备份分片布置可能如下:
- 每组三个服务器服务一个分片/链
- 分片A: S1 S2 S3
- 分片B: S4 S5 S6
- 问题:一些服务器的负载可能比其他服务器更重
- 每个组中的主服务器可能较慢,而其他服务器则有空闲容量
- 头部和尾部可能比中间部分负载更重
- 负载较轻的服务器浪费资源
- 问题:替换故障的副本需要很长时间
- 新服务器必须通过网络从剩余副本中的一个获取整个磁盘的数据
- 以千兆比特/秒的速度传输一TB需要两个小时
- 在完成之前,剩余副本存在显著的失败风险
这种布置可能导致资源的不均匀使用和故障恢复时间长的问题。论文中的后续节可能提供了更好的布局和解决方案,建议详细查看这些部分以获取更全面的信息。
- 每组三个服务器服务一个分片/链
-
更好的计划(在第5.4节中称为 “rndpar”):
-
将数据分割为比服务器更多的分片
- 这样每个分片要比之前的布置中的分片小得多。
-
每个服务器是多个分片组的副本
- 分片A: S1 S2 S3
- 分片B: S2 S3 S1
- 分片C: S3 S1 S2
- (这是一个规则的布置,但一般来说可以是随机的)
-
对于主/备份系统,服务器在一些组中是主服务器,在其他组中是备份服务器。
- 例如,对于分片A,S1可能是主服务器,而S2和S3是备份服务器。
-
对于链式复制,一个服务器可能在某些组中是头部,而在其他组中是尾部或中间部分。
- 例如,对于分片A,S1可能是头部,S2是中间,S3是尾部。
通过这样的布置,请求处理工作可能更加均衡,因为每个服务器参与了多个分片组,而且分片的大小相对较小。这提高了系统的整体性能和容错性。
-
-
rndpar如何修复速度
- 假设一个服务器发生故障,并且该服务器参与了M个副本组,对应M个分片。与其指定一个替代服务器,“rndpar” 选择M个替代服务器,每个分片选择不同的服务器。
- 这些都是现有的服务器,我们将赋予它们新的职责。
- 这意味着对这M个分片的修复可以并行进行。与传统方法相比,其中一次只替换一个服务器,“rndpar” 的并行修复能够显著加速整个过程。修复时间将变为原来的1/M。
-
如果三台随机服务器出现故障,rndpar 会如何处理?
- 如果三个随机服务器发生故障,“rndpar” 在处理这种情况时可能会面临挑战。随着每个服务器上的分片数量增加,有可能某个分片的三个副本正好分布在发生故障的三个随机服务器上。这并不理想。
- “rndpar” 提供了快速修复的优势,但由于有更高的概率使得一些故障会导致某个分片的所有副本都失效(参见Figure 7),因此这个优势在一定程度上受到了削弱。这也是在设计系统时需要权衡的一方面。在这种情况下,系统可能需要实施一些机制来缓解这种潜在的问题,例如增加冗余度,提高数据的可靠性。
-
结论:
- Chain Replication 是对 ROWA(Read One Write All)方案的描述中最清晰的之一。
- 它在平衡工作方面表现出色。
- 它在故障后重新同步副本方面有简单而有效的方法。
- 具有影响力,被应用在 EBS、Ceph、Parameter Server、COPS、FAWN 等系统中。
- 它是许多设计(主/备份、法定人数等)中的一种,具有不同的性能特点。
-
实验表明
-
主要收获(5.1):
- Chain Replication 的吞吐量与主/备份系统一样高,因为它受到头部/主服务器CPU的限制。
- 对于0%更新的情况,Chain Replication 受尾部瓶颈限制,而主/备份系统受主服务器瓶颈限制。
- 对于100%更新的情况,Chain Replication 受头部瓶颈限制,而主/备份系统受主服务器瓶颈限制。
- 只有在中间情况下存在差异,因为 Chain Replication 将工作分担在头部和尾部之间。
- 但是,这里假设网络通信是免费的;在实际生活中,主/备份系统存在问题,因为主服务器必须发送给所有备份。
- 但是,在真实世界中,写入延迟是一个问题,因为客户端通常在等待“已提交”的回复。
-
主要收获(5.2):
- 假设有数千条链和数十个服务器。
- 思路:将数据分布在许多链上,然后将这些链分布在适量的服务器上,以便每个服务器都参与多个链,有的作为头部,有的作为尾部,有的在中间。
- 这样可以平衡作为头部和尾部与作为中间部分的负载。
- 图5似乎并未表达出太多信息,可能只是说明如果你只有25个客户端,那么大约25个服务器就足够了。
-
主要收获(5.3):
- 假设有数千条链和数十个服务器。
- 修复时间是一个很大的问题,因为单个服务器可以存储大量数据,需要花费数小时才能在单个网络链路上传输。
- 当单个服务器发生故障时,需要将其复制的数据的责任分散到多个其他服务器上,以实现快速并行修复。
-
主要收获(5.4):
- 假设有数千条链和数十个服务器。
- 对于并行恢复速度来说,最好的情况是没有约束且随机放置,这样在单个故障后,恢复流量的源和目的地都可以均匀分布。
- 但是,如果链随机分布在服务器上,那么任何三个(如果链长度为3)随机服务器故障的组合都有很大的机会摧毁某条链的所有副本。
- 环形拓扑结构是一种妥协:你不能将恢复负载扩散得很广,但几个随机服务器故障不太可能摧毁任何一条链的所有副本。
- 对于他们的设置,重建的速度似乎比同时发生的故障摧毁一条链更重要。
- 但是,他们假设单个服务器的平均故障间隔(MTBF)为24小时,这意味着当修复需要数小时时,快速修复是至关重要的,但24小时似乎是一个不切实际地短的时间。
-
-
CRAQ 如何应对网络分区并防止大脑分裂?
- CRAQ(以及Chain Replication)本身没有防范网络分区和防止拆分脑的机制。在短期内,如果链节点没有响应,其他链成员必须等待。CRAQ和CR依赖于一个单独的配置服务,该服务决定构成每个链的服务器。配置服务监视服务器以形成对谁是活动的意见,每当一个服务器似乎无法访问时,配置服务决定链中哪些服务器仍然活动,并告知这些服务器(以及客户端)新的链设置。配置服务通常使用Paxos、Raft或(在CRAQ的情况下)ZooKeeper构建,以使它们具有容错性,并且它们自己避免了拆分脑,即使有分区。从高层次上看,无论是GFS还是VMware-FT都遵循了这种模式(GFS的主节点监视服务器的活动性并选择主服务器;VMware-FT的测试和设置服务在服务器死机时选择唯一的服务器)。
-
Chain Replication与Raft或Paxos相比有哪些权衡之处?
- CRAQ和Raft/Paxos都是复制状态机。它们可以用于复制任何适合状态机模型的服务(基本上,一次处理一个请求流)。 Raft/Paxos的一个应用是对象存储 - 你将在实验3中在Raft之上构建对象存储。同样,CRAQ的基础机制也可以用于除存储之外的其他服务,例如实现锁服务器。
- CR和CRAQ可能比Raft更快,因为CR头执行的工作比Raft领导者少:CR头只将写操作发送到一个副本,而Raft领导者必须将所有操作发送到所有追随者。 CR在读取方面也具有性能优势,因为它从尾部提供读取服务(而不是头部),而Raft领导者必须处理所有客户端请求。
- 然而,Raft/Paxos和CR/CRAQ在故障属性上存在显着差异。 Raft(以及Paxos和ZooKeeper)即使少数节点崩溃、变慢、不可靠或分区,也可以继续操作(完全没有暂停)。如果类似的情况发生在CRAQ或CR链中,它们必须停止,并等待配置管理器决定如何继续。另一方面,在CR/CRAQ中,故障后的情况要简单得多;请回顾Raft论文中的第7和第8图。
-
与GFS中使用的主/备份机制相比,Chain Replication的速度是否会显著快于或慢于主/备份机制?
- 如果只有两个副本,可能没有太大的差异。虽然也许在写入方面,CR可能会更快,因为尾部可以直接将响应发送给客户端;在经典的主/备份方案中,主节点必须在响应客户端之前等待备份确认写入。
- 如果有三个或更多副本,在经典的主/备份系统中,主节点必须将每个写操作发送到每个副本。如果写入数据较大,这些网络发送可能会对主节点造成重大负载。Chain Replication将这个网络负载分布在所有副本上,因此CR的头节点可能不像经典主节点那样成为性能瓶颈。另一方面,也许在CR中,对于写操作,客户端观察到的延迟会更高。
-
论文的引言部分提到可以使用多个链来解决中间链节点不提供读取服务的问题。这是什么意思?
-
在Chain Replication中,只有头部和尾部直接提供客户端请求服务;其他副本用于容错而不是性能。由于头部和尾部的负载可能比中间节点的负载更高,可能出现性能受到头/尾限制的情况,但中间节点却有大量空闲CPU的情况。CRAQ通过将读取工作移动到中间节点来利用这些空闲的CPU。
-
引言提到了这种替代方法。一个数据中心可能有许多不同的CR链,每个链为对象的一个分片提供服务。假设有三个服务器(S1、S2和S3)和三个链(C1、C2和C3)。那么可以让这三个链分别为:
C1: S1 S2 S3
C2: S2 S3 S1
C3: S3 S1 S2 -
现在,假设三个链上的活动大致相等,那么三个服务器的负载也将大致相等。特别是提供客户端请求服务的负载(头部和尾部)将在三个服务器之间大致均分。
-
这是一个相当合理的安排;CRAQ只在某些链比其他链的负载更高的情况下才更好。
-
-
CRAQ的故障模型是否是非拜占庭故障?
- CRAQ无法处理拜占庭故障,只能处理停机故障。
- 很少有系统在面对拜占庭故障时表现出色,通常在性能或灵活性方面需要做出牺牲。我知道的两种主要方法是:首先,基于Castro和Liskov的一篇名为“Practical Byzantine Fault Tolerance(PBFT)”的论文的系统;PBFT类似于Raft,但通信轮次更多,使用了密码学。其次,允许客户端直接检查服务器返回结果正确性的系统,通常通过使用加密哈希或签名。这可能会比较棘手,因为客户端需要防范返回数据签名或哈希是正确的,但不是最新值的服务器。类似这样的系统包括SUNDR和比特币。