MIT6.824/lecture-04-vmware-ft/4.4-non-determistic.md
2022-01-25 02:41:31 +00:00

57 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 4.4 非确定性事件Non-Deterministic Events
好的目前为止我们都假设只要Backup虚机也看到了来自客户端的请求经过同样的执行过程那么它就会与Primary保持一致但是这背后其实有很多很重要的细节。就如其他同学之前指出的一样其中一个问题是存在非确定性Non-Deterministic的事件。虽然通常情况下代码执行都是直接明了的但并不是说计算机中每一个指令都是由计算机内存的内容而确定的行为。这一节我们来看一下不由当前内存直接决定的指令。如果我们不够小心这些指令在Primary和Backup的运行结果可能会不一样。这些指令就是所谓的非确定性事件。所以设计者们需要弄明白怎么让这一类事件能在Primary和Backup之间同步。
![](<../.gitbook/assets/image (274).png>)
非确定性事件可以分成几类。
* 客户端输入。假设有一个来自于客户端的输入这个输入随时可能会送达所以它是不可预期的。客户端请求何时送达会有什么样的内容并不取决于服务当前的状态。我们讨论的系统专注于通过网络来进行交互所以这里的系统输入的唯一格式就是网络数据包。所以当我们说输入的时候我们实际上是指接收到了一个网络数据包。而一个网络数据包对于我们来说有两部分一个是数据包中的数据另一个是提示数据包送达了的中断。当网络数据包送达时通常网卡的DMADirect Memory Access会将网络数据包的内容拷贝到内存之后触发一个中断。操作系统会在处理指令的过程中消费这个中断。对于Primary和Backup来说这里的步骤必须看起来是一样的否则它们在执行指令的时候就会出现不一致。所以这里的问题是中断在什么时候具体在指令流中的哪个位置触发对于Primary和Backup最好要在相同的时间相同的位置触发否则执行过程就是不一样的进而会导致它们的状态产生偏差。所以我们不仅关心网络数据包的内容还关心中断的时间。
![](<../.gitbook/assets/image (275).png>)
* 另外,如其他同学指出的,有一些指令在不同的计算机上的行为是不一样的,这一类指令称为怪异指令,比如说:
* 随机数生成器
* 获取当前时间的指令,在不同时间调用会得到不同的结果
* 获取计算机的唯一ID
![](<../.gitbook/assets/image (276).png>)
* 另外一个常见的非确定事件在VMware FT论文中没有讨论就是多CPU的并发。我们现在讨论的都是一个单进程系统没有多CPU多核这种事情。之所以多核会导致非确定性事件是因为当服务运行在多CPU上时指令在不同的CPU上会交织在一起运行进而产生的指令顺序是不可预期的。所以如果我们在Backup上运行相同的代码并且代码并行运行在多核CPU上硬件会使得指令以不同于Primary的方式交织在一起而这会引起不同的运行结果。假设两个核同时向同一份数据请求锁在Primary上核1得到了锁在Backup上由于细微的时间差别核2得到了锁那么执行结果极有可能完全不一样这里其实说的就是在两个副本上不同的线程获得了锁。所以多核是一个巨大的非确定性事件来源VMware FT论文完全没有讨论它并且它也不适用与我们这节课的讨论。
![](<../.gitbook/assets/image (277).png>)
> 学生提问如何确保VMware FT管理的服务只使用单核
>
> Robert教授服务不能使用多核并行计算。硬件几乎可以肯定是多核并行的但是这些硬件在VMM之下。在这篇论文中VMM暴露给运行了Primary和Backup虚机操作系统的硬件是单核的。我猜他们也没有一种简单的方法可以将这里的内容应用到一个多核的虚拟机中。
所有的事件都需要通过Log Channel从Primary同步到Backup。有关日志条目的格式在论文中没有怎么描述但是我Robert教授猜日志条目中有三样东西
1. 事件发生时的指令序号。因为如果要同步中断或者客户端输入数据最好是Primary和Backup在相同的指令位置看到数据所以我们需要知道指令序号。这里的指令号是自机器启动以来指令的相对序号而不是指令在内存中的地址。比如说我们正在执行第40亿零79条指令。所以日志条目需要有指令序号。对于中断和输入来说指令序号就是指令或者中断在Primary中执行的位置。对于怪异的指令Weird instructions比如说获取当前的时间来说这个序号就是获取时间这条指令执行的序号。这样Backup虚机就知道在哪个指令位置让相应的事件发生。
2. 日志条目的类型,可能是普通的网络数据输入,也可能是怪异指令。
3. 最后是数据。如果是一个网络数据包那么数据就是网络数据包的内容。如果是一个怪异指令数据将会是这些怪异指令在Primary上执行的结果。这样Backup虚机就可以伪造指令并提供与Primary相同的结果。
![](<../.gitbook/assets/image (278).png>)
举个例子Primary和Backup两个虚机内部的guest操作系统需要在模拟的硬件里有一个定时器能够每秒触发100次中断这样操作系统才可以通过对这些中断进行计数来跟踪时间。因此这里的定时器必须在Primary和Backup虚机的完全相同位置产生中断否则这两个虚机不会以相同的顺序执行指令进而可能会产生分歧。所以在运行了Primary虚机的物理服务器上有一个定时器这个定时器会计时生成定时器中断并发送给VMM。在适当的时候VMM会停止Primary虚机的指令执行并记下当前的指令序号然后在指令序号的位置插入伪造的模拟定时器中断并恢复Primary虚机的运行。之后VMM将指令序号和定时器中断再发送给Backup虚机。虽然Backup虚机的VMM也可以从自己的物理定时器接收中断但是它并没有将这些物理定时器中断传递给Backup虚机的guest操作系统而是直接忽略它们。当来自于Primary虚机的Log条目到达时Backup虚机的VMM配合特殊的CPU特性支持会使得物理服务器在相同的指令序号处产生一个定时器中断之后VMM获取到这个中断并伪造一个假的定时器中断并将其送入Backup虚机的guest操作系统并且这个定时器中断会出现在与Primary相同的指令序号位置。
> 学生提问:这里的操作依赖硬件的定制吗?(实际上我听不清,猜的)
>
> Robert教授是的这里依赖于CPU的一些特殊的定制这样VMM就可以告诉CPU执行1000条指令之后暂停一下方便VMM将伪造的中断注入这样Backup虚机就可以与Primary虚机在相同的指令位置触发相同的中断执行相同的指令。之后VMM会告诉CPU恢复执行。这里需要一些特殊的硬件但是现在看起来所有的Intel芯片上都有这个功能所以也不是那么的特殊。或许15年前这个功能还是比较新鲜的但是现在来说就比较正常了。现在这个功能还有很多其他用途比如说做CPU时间性能分析可以让处理器每1000条指令中断一次这里用的是相同的硬件让微处理器每1000条指令产生一个中断。所以现在这是CPU中非常常见的一个小工具。
>
> 学生提问如果Backup领先了Primary会怎么样
>
> Robert教授 场景可能是这样Primary即将在第100万条指令处中断但是Backup已经执行了100万零1条指令了。如果我们让这种场景发生那么Primary的中断传输就太晚了。如果我们允许Backup执行领先Primary就会使得中断在Backup中执行位置落后于Primary。所以我们不能允许这种情况发生我们不能允许Backup在执行指令时领先于Primary。
>
> VMware FT是这么做的。它会维护一个来自于Primary的Log条目的等待缓冲区如果缓冲区为空Backup是不允许执行指令的。如果缓冲区不为空那么它可以根据Log的信息知道Primary对应的指令序号并且会强制Backup虚机最多执行指令到这个位置。所以Backup虚机的CPU总是会被通知执行到特定的位置就停止。Backup虚机只有在Log缓冲区中有数据才会执行并且只会执行到Log条目对应的指令序号。在Primary产生的第一个Log并且送达Backup之前Backup甚至都不能执行指令所以Backup总是落后于Primary至少一个Log。如果物理服务器的资源占用过多导致Backup执行变慢那么Backup可能落后于Primary多个Log条目。
网络数据包送达时有一个细节会比较复杂。当网络数据包到达网卡时如果我们没有运行虚拟机网卡会将网络数据包通过DMA的方式送到计算机的关联内存中。现在我们有了虚拟机并且这个网络数据包是发送给虚拟机的在虚拟机内的操作系统可能会监听DMA并将数据拷贝到虚拟机的内存中。因为VMware的虚拟机设计成可以支持任何操作系统我们并不知道网络数据包到达时操作系统会执行什么样的操作有的操作系统或许会真的监听网络数据包拷贝到内存的操作。
我们不能允许这种情况发生。如果我们允许网卡直接将网络数据包DMA到Primary虚机中我们就失去了对于Primary虚机的时序控制因为我们也不知道什么时候Primary会收到网络数据包。所以实际中物理服务器的网卡会将网络数据包拷贝给VMM的内存之后网卡中断会送给VMM并说一个网络数据包送达了。这时VMM会暂停Primary虚机记住当前的指令序号将整个网络数据包拷贝给Primary虚机的内存之后模拟一个网卡中断发送给Primary虚机。同时将网络数据包和指令序号发送给Backup。Backup虚机的VMM也会在对应的指令序号暂停Backup虚机将网络数据包拷贝给Backup虚机之后在相同的指令序号位置模拟一个网卡中断发送给Backup虚机。这就是论文中介绍的Bounce Buffer机制。
> 学生提问怪异的指令Weird instructions会有多少呢
>
> Robert教授怪异指令非常少。只有可能在Primary和Backup中产生不同结果的指令才会被封装成怪异指令比如获取当前时间或者获取当前处理器序号或者获取已经执行的的指令数或者向硬件请求一个随机数用来加密这种指令相对来说都很少见。大部分指令都是类似于ADD这样的指令它们会在Primary和Backup中得到相同的结果。每个网络数据包未做修改直接被打包转发然后被两边虚拟机的TCP/IP协议栈解析也会得到相同的结果。所以我预期99.99%的Log Channel中的数据都会是网络数据包只有一小部分是怪异指令。
>
> 所以对于一个服务于客户端的服务来说我们可以通过客户端流量判断Log Channel的流量大概是什么样子因为它基本上就是客户端发送的网络数据包的拷贝。