MIT 6.824 学习记录:FT VM 论文阅读与思考
上周阅读了 MIT 6.824 课程中的论文 “The Design of a Practical System for Fault-Tolerant Virtual Machines”,初步理解了 Fault-Tolerant Virtual Machine 的系统设计。以下是我对论文部分内容的记录与思考整理。
基本概述
Fault-Tolerant Virtual Machine 是一套基于复制(replication)的容错方案,核心思想是为主虚拟机配置同步运行的备用虚拟机,从而在主虚拟机宕机时,由备用虚拟机接管其工作,实现整体的容错能力。
在该分布式系统的设计中,我们需从多个维度思考方案及可能面临的问题,包括易用性、数据带宽、可用性及性能等方面。其中,最关键的是两个核心问题:
如何同步
如何容错
同步方案
论文开篇即指出,该方案基于复制(replication)模型,因此首要问题是主备之间的同步机制设计。
一种直观的方式是通过数据快照等手段,直接同步主机的所有信息。但这种方法存在一个明显的问题:信息量庞大,持续同步将占用大量带宽。
不过虚拟机的一个特点是由 hypervisor 控制,这意味着我们可以捕获其全部输入输出。因此,如果采用黑盒思路,可以将虚拟机抽象为一个状态机模型。只要主备虚拟机以相同顺序接收相同输入,它们就会经历相同的状态转变,最终达到一致状态。这样,仅需在主备之间传输少量信息即可完成同步。
当然,这里也引出了几个关键问题:
信息如何传递?
传递的信息如何被使用?
状态机模型要求操作是确定性的,但像 IO 这样的操作具有不确定性,应如何处理?
容错处理的具体机制是什么?
主备消息传递
论文中提供了一张系统架构图,如下所示:
可以看到,主备之间通过一个 logging channel 实现消息传递。具体来说,是主备双方的 hypervisor 各自维护一个较大的 buffer(缓冲区),用于存储 log entry。每个 entry 是一个消息单元,保存了一次状态变化所需的输入信息,以及可能涉及不确定操作的附加信息。这一设计让我联想到 MySQL 中的 redolog 以及 Redis 的 AOF 机制。
从设计角度来看,这实际上是一种典型的生产者-消费者模型:主机作为生产者,将同步消息写入本地 hypervisor 的 log buffer,消息随后通过 channel 传输到 backup 的 log buffer,由备机取出并执行,从而完成消费过程。
消息的使用
对于主备的协作方式,论文中另一张 FT Protocol 图也很直观地展示了整体设计:
如图所示,主备虚拟机是并行运行的,并通过前述的 logging channel 进行异步事件的交互。每当 primary 接收到一个输入,它都会同步一份消息给 backup。backup 在接收到消息后,会以与 primary 相同的方式执行这条输入,从而保持最终一致性。
从流程可以看出,主备的执行逻辑高度相似。但由于网络传输存在延迟,备机可能存在一定 lag。为确保系统状态的一致性与可靠性,设计上将 primary 的每一次输出操作视为一个 checkpoint,只有当 backup 执行到相同状态并发送 ack 消息确认后,primary 才会继续执行该输出操作。
读到这里我一度产生疑问:这样的设计是否会导致 primary 出现频繁阻塞,进而严重影响性能?🫠
但很快我意识到这里的设计非常巧妙:output 操作是由 hypervisor 控制的。也就是说,尽管 output 被“阻塞”了,但 primary 实际上可以继续正常执行,只有当 backup 的 ack 消息到达后,output 才会真正对外发生。这就是论文中的 output rule——由于 output 会对外界产生实际影响,必须确保 backup 已经同步到能接管 primary 的状态,才能安全输出。
我觉得这个设计有点类似于异步 IO,也就是说,primary 的执行流程本身不被阻塞,只有在 backup 就绪后才触发 output。这让我最初联想到 2PC(两阶段提交),但深入思考后发现两者仍存在明显区别。尽管此处也涉及状态确认,但没有回滚机制。即使 primary 崩溃,它之前发给 backup 的消息仍保留,因此不会造成操作回滚,整体效率更高。
另外一个有趣的点是,前面提到主备的消息模型类似生产者-消费者关系:当消息积压时,生产者(primary)会被阻塞;而当没有消息时,消费者(backup)会被阻塞。这种机制有助于控制主备之间的 lag,保证 backup 在 primary 宕机时能够迅速接管。此外,为避免延迟过大或频繁阻塞,ack 消息中会包含一些时间信息,系统会据此判断是否对 primary 实施 CPU 限速,使其主动“减速”以等待 backup 跟上,后续再逐步解除限制。这种设计在尽可能不影响性能的前提下,提升了系统的同步效率与稳定性。
同步细节
前文我们已了解该系统的整体同步机制,但在实际实现中,仍有许多关键的细节问题需要进一步探讨,尤其是涉及 I/O 等非确定性操作时,如何实现精确同步。
首先来看磁盘 I/O。这部分的设计相当巧妙,在 FT VM 的系统架构图中可以看到,其采用了 Shared Disk(共享磁盘)的方案,即主机(primary)与备机(backup)共用同一个文件系统。相较于主备各自独立磁盘的设计,这种方式显著减少了文件系统同步的开销。同时,也规避了备机进行写操作的复杂性:在此架构下,只有主机可以执行实际的写操作,备机仅进行读取。
但由于主备之间存在一定的时延,主机对磁盘的写操作可能与备机的读操作发生冲突。为此,系统采取与输出同步类似的策略,即使用 checkpoint,确保这类对外部世界有副作用的非确定性操作能在主备之间保持一致性。
接下来是网络 I/O。在传统虚拟机系统中,为提升性能,网络 I/O 通常采用异步处理等优化方式。然而,这会导致在备机重放日志时存在不确定性,因此在 FT VM 中,这些优化被禁用,取而代之的是一种可追踪的同步机制:
每当网络包到达时,系统不会直接将其写入 VM 内存,而是通过 guest OS 触发一次 trap(陷入到 hypervisor)
hypervisor 在 trap 点记录该输入事件的日志,并随后更新缓冲区
这样一来,备机 VM 就能够在相同的指令位置重放相同的 trap,从而保证输入操作的一致性
发送数据(输出)同样采用类似策略:
所有发送操作必须在 hypervisor 的控制范围内执行
主机只有在备机接收到相应的日志记录并返回 ack 之后,才会真正将数据发送至网络
原先所有的网络 I/O 都是直接进行的,现在则必须经过以下步骤:
trap + 日志记录
等待 ack
批量处理
为了降低上述机制对性能的影响,论文中提出了两方面的优化措施:
上层优化:将多次操作合并成一次 trap 或一次中断,利用批处理机制一次性发送,提高效率
底层优化:日志传输过程中不涉及线程上下文切换(no thread context switch),并采用类似 Linux 中
tasklet
的 deferred execution callback(延迟执行回调)机制,当 TCP 协议栈接收到数据时立即触发回调处理,避免阻塞与等待
容错操作细节
在同步机制落实之后,容错处理相对来说就没有那么复杂了,但其中仍有一些重要的实现细节值得探讨。
系统使用基于 UDP 的 心跳检测 来判断主机是否正常运行,此外也可以通过 日志通道(logging channel) 来判断系统状态。如果心跳检测发现主机宕机,或日志通道出现长时间中断,系统就会判定主机失效,并触发容错机制。
在容错过程中,无论是主机还是备机发生故障,系统中的另一方都会触发所谓的 go live 操作。对于 primary 来说,这意味着进入真正的运行状态,不再向 logging channel 发送日志(此处我理解仍存疑,某些情况下可能需要等待备机重启或通过复制在新主机上重新启动备机)。而备机的 go live 操作意味着它正式接管,成为新的主机,并从主机故障前的状态继续执行。
这实际上构成了一个类似于选主(leader election)的过程。任何分布式系统在执行选主时都可能遇到 split-brain(脑裂) 问题——即主备由于网络分区无法判断对方状态,导致系统中同时存在多个主节点,从而破坏一致性。
FT VM 通过一个简单但有效的机制避免了该问题:确保系统中只有一个主节点对外进行输出。配合前文提到的 shared disk,系统可以使用 文件的原子 compare-and-swap(CAS)操作 来保证只有一个主节点。当备机尝试切换为主节点时,会先尝试原子写入 shared storage;如果写入失败,就说明另一个主节点可能仍在运行。此时,为防止脑裂,备机会主动终止自身运行(commits suicide)。
这一机制凸显了 shared disk 的另一个优势:除了减少同步开销,它还能在不引入额外不确定性的情况下,帮助系统维持全局一致性。这让我联想到传统后端开发中,类似 Redis 分布式 session 的实现,也利用了 shared storage 和原子操作来实现状态一致,非常有启发。
总结
以上是我在初次阅读论文过程中所整理的内容与思考,可能仍存在部分理解偏差或不全面之处。希望在后续课程与实验中,能够进一步深化对该系统的设计理念与实现机制的理解。
资料链接:
MIT 6.824 课程安排:https://pdos.csail.mit.edu/6.824/schedule.html
论文下载地址:https://pdos.csail.mit.edu/6.824/papers/vm-ft.pdf