The Design of a Practical System for Fault-Tolerant Virtual Machines
摘要
通过在备份机上运行相同的操作,实现企业级FT(fault-torent)虚拟机。 易于使用,可在商业机跑, 性能只减少10%。考虑到长距离容错,主-从机之间的网络带宽应该小于10%。 故障发生后,自动恢复需要很多其他的组件,因此,本系统还实现了其余的组件,解决了很多实际应用中遇到的问题。
Introduction
FT 系统中,故障发生后,备份机需要很快接管。备份机需要很接近primary机状态,两种方式:
1.replicate all states: CPU, memory and I/O device, however, need more bandwidth
2. state machine approach: use much less bandwidth. Treat the server as deterministic machine.(a. start as same initial state; b. receive the request in the same order)
物理机上协调状态很难,但是管理程序下VM是个很好的平台,VM 本身就是被很好定义的状态机。当使用物理机,VM有很多不确定的操作(中断,时钟延时),需要其余的信息保证同步。 管理程序可以保证所有重要的操作在 备份机上全部执行。因此可以在普通商业机上执行,带宽要求也不高,复制可以跨区进行,更加可靠。
FT 备份可以在VSphere 4.0上实现,这种VM充分虚拟x86, 因此可以把备份技术应用到所有x86机器上去。 除了提供硬件级别的FT,故障发生过时,系统可以通过启动新的机器,自动进行冗余恢复。此时, FT 只支持单处理器VM。多核处理器有很多不确定性。
Bressoud and Schneider描述了原型机。在这个基础上,这里做了一些改进,提升性能。还设计了其他组件,去处理实际问题。 和所有实用系统一样,只处理 fail-stop 故障(在外部发现感知之前处理故障)
文章结构:描述基本设计;和详细协议; 需要解决的实际问题;性能测试结果;相关工作
2 Basic FT Design
-
set primary VM, and backup VM execute the same operation to keep sychronized.
-
primary and backup share the storage(4.1 discuss non-share disk)
-
netword input come to the primary VM only the VM advertise its presence. Other
-
inputs go only to the primary VM
input to primary VM is sent to backup VM using loggin channel. 额外的信息保证非确定的操作用相同的方式运行。 The difference is that, hypervisor drop the output of backup
combine to method to detect failure: 1. heartbeating between the servers; 2. monitoring of the traffic on logging channel. Must ensure that only one VM take over executing
2.1 deterministic replay implementation
Principle:
- initial state is same
- the exact same input in the same order
The problem
-
a broad set on-deterministic operations will affect the VM’s state
-
No deterministic event and operations
three challenges
(1)capturing all input
(2) correctly applying input
(3) not influence the performance
Some solutions
- non deterministic operations are recorded in Log(以日志形式保存下来,然后顺序执行)
- divide executions in epoches: all non-deterministic operations are deliverd at the end of epoch(但本系统没用)
2.2 Fault Tolerance 协议
简介:
(1)Use log to record the execution of primary VM, and log are sent to backup VM via logging channel.
(2)must augument the log with strict FT, to get FT
最基本的Output Requirement就是:故障发生,备份机接管了primary 之后,备份机的输出要和primary 机器保持一致
解决这个Output requirement 方法:
(1)延迟发送所有对外输出,直到备份机也能有相同的输出。
(2)备份机接受log entry 早于对外输出
主机在一次输出之后恰好挂机了, 那么备份机比如在对外输出的后的这一时刻上线,否则会出现不确定性。
Output Rule:主机在输出前,记下输出日志,备份机ack 这条日志之后,主机才能对外输出
(只需要延迟primary 输出,不要延迟primary其余运行指令)
图2就是primary 和Backup运行的时间线,直到Backup ack了,primary才对外输出。
2.3 相关故障检测
故障出现之后,primary和backup必须快速反应:
- backup 故障: primary 停止发送日志,
- primary 故障, backup 上线: 相对复杂,且需要一段时间(接收了一些日志,并且ack了,但是没有运行到相关point。 backup 运行完最后一个log, 然后升级成Primary,还要广播MAC地址,改变disk IO
failure detection 是通过心跳实现,primary 和 backup之间的心跳停止了,发生故障
failure detection 容易受脑裂机制影响:backup收不到心跳,可能是故障,也有可能网络断开了;backup 成为primary, 原来的primary 还在,就会出现故障。
解决脑裂:使用共享disk, VM 上线,尝试原子test and set 操作, 成功了上线,失败了就不上线,这种方法不会引入其他问题
一旦有机器故障,新的VM上线, 那么会在其他Host重启新的 backup VM。
3 FT 的实际实现
创建一个FT系统,还要实现其他很多组件
3.1 启动和重启FT
主要新增机制:启动一个和Primary 一样状态的backup 机器,重启的时候也会用。 且这个机制不能影响primary运行。
使用现有VMware VMotion的部分功能(可在1s内完成热迁移):使用修改过的VMotion, clone一个 VM到其他VM, 然后设立log channel, 设置Source为Primary, destinatin为backup, 只打断primary 1s 的运行, 简单、对主primary无额外影响
还有一个方面:具体选择哪台机器运行VM
VSphere 使用Clustering service 管理资源信息: cluster service 决定最合适的机器(一般是由机器的资源使用情况和其他限制条件决定),故障发生后几分钟内重建冗余机器, 没有很明显的停顿
3.2 Logging channel管理
每个hypervisor 管理了一个很大的buffer, primary 将日志写入buffer, backup 机器从buffer消费日志。backup的buffer 收到日志之后,很快返回ack, 让primary 决定是否延迟输出。
backup 的buffer 为空时,将被阻塞,直到新的日志从channel写入,primary的buffer满了,日志无法写入时,primary 将停止运行,直到buffer有剩余空间。这会对client端有影响,因为primary 机器可能完全停止,因此需要有合理的设计,尽量减少 primary buffer塞满的可能。
primary buffer满的原因之一是: backup VM运行太慢了,日志消费太慢了。一般来说VM determinitic replay中,primary 和 backup的运行速度基本相同,但是如果物理主机负担过大,那么backup 无法获得硬件资源,减低速度。
为了避免外界感知到停顿,执行延迟时间不能太大,primary 挂掉之后, backup 运行完buffer的日志,然后接替主机,与外界交互(避免故障)。backup接替primary的时间 = 故障察觉时间 + 延迟执行时间。 延迟执行时间越短(控制在1秒),故障时间就越短。
因此需要采用额外的措施,为primary 减速,避免backup VM 落后太多。理论上backup log 落后于primary 100ms以内, 超过这某个数字(1s),FT 逐渐减低给primary的CPU资源,知道Backup 赶上primary。之后恢复给primary的CPU资源。这种降速很少发生,除非系统的负载常高。
3.3 FT VM 上的操作
如何处理对primary 的控制操作也是一个问题。例如, primary VM 被命令关机,然后backup 也要关机,而不是接管主机; 资源变化(如增加CPU资源), 这类操作也会通过logging channel, 发送给backup, 以达到同样的控制。
大多控制都会在primary 和backup 同时执行,除了VMotion。primary 和 backup不会迁移到同一个server,这样FT就无法保证了(没有意义,server挂了,primary 和backup都会挂)
VMotion(VMware提供的一种迁移操作)有额外操作,backup VM需要断开月原来primary,然后连接上新的primary。 Backup VMotion 操作和primary 有所不同,因为迁移的时候,IO 操作必须静止。primary静止IO很容易,直到迁移完成。但是Backup VM需要重现primary VM 操作,然后在同一点完成IO操作。Backup在完成VMotion最终的切换前,通过loggin channel控制primary 暂时静止IO 操作,然后完成迁移切换。
3.4 硬盘IO 上的实现问题
有一些不易察觉的小问题,比如部分磁盘操作是并发,不是determinitic。这类操作数量很少,这里的解决方法是:记录这些IO 轨迹,然后强制在primary 和 backup 主机上顺序执行。
内存访问竞争(注释:读了很久,总的意思就是app读内存时,刚刚有磁盘读更新了内存,产生错误):disk操作和 app 、OS 竞争内存访问。application/OS 读内存的同时, 从磁盘读操作也在进行,会出现non-determinitic 结果。解决方法:page protection: VM 中application/OS 恰好访问的page是 disk操作的page, 就会停顿VM。 使用bounce buffers来实现页面保护, disk read 进行时,将指定数据读入bounce buffer,只有IO 操作结束后,才将数据复制进内存。disk write时,将数据先复制到bounce buffer,然后再将bounce buffer里面的数据写入磁盘。
当primary 故障时,backup 接替,这个时候进行disk IO 操作,新上任接替的 primary VM 无法知道硬盘操作是否顺利完成。 IO 操作不是在新接替的primary 发出的,所以primary 也不会对外发出 IO 完成的信号,导致外部的client 会放弃或者重置步骤。即使 IO 成功完成也可以返回错误, 也返回一个错误,但是,客户操作系统可能无法很好地响应来自其本地磁盘的错误。 这里的做法: 可以重启挂起的IO操作, 即它们是幂等的。
3.5 网络IO上的实现问题
Sphere 在VM networking上优化了很多,基于hypervisor 异步更新VM的网络设备,但会增加non-determinism。除非能保证在primary和backup的更新发生在同一点。
这里做的修改:禁止异步网络优化,传入数据包被强制进去hypervisor, 然后日志记录操作,应用于VM。 代码从传送队列正常拉取数据包也被禁止了,而是强制传入hypervisor。
取消异步更新,还有延迟发送数据包给外部影响了性能,这里使用两个方法提升VM 网络性能: 第一种: 实现了集群优化,减少VM trap 和 中断,数据流快速传输时, hypervisor 一组数据包进行一次trap;同样地, hypervior,对一组数据包进行一次中断, 以减少interrupts 操作。另外的优化:减少数据包的传输延迟, 主要减少发送给backup log 消息的时间,然后接受ack的时间。这里做的优化是:发送log entry和接受ack时,无线程的上下文切换。 VSphere 将function 注册在TCP 栈上, 然后只要TCP 数据包到达就会被deferred -execution context调用 (类似于回调函数?),提升发送log和ack log速度。
4 备份设计方案
4.1 共享/非共享磁盘
默认设计中,primary 和backup 共享虚拟磁盘, 共享磁盘被视为外部条件,只有primary VM 才能写入。
另外的设计是:primary和backup 各自有虚拟磁盘,如图4所示。non-share disk 被视为VM 内部,而不是外部, 硬盘写操作不用延迟,这种设计也有好处,当primary 和backup 同时无法访问共享磁盘的时候。这种设计适用于 共享内存价格昂贵或者不可用,或者两个FT server距离遥远。 但是非共享磁盘的缺点是:两份磁盘必须在某些行为上显式地同步。此外,磁盘在一个故障之后,很容易脱离同步,所以必须显式地重启同步, 也就是FT VMotion 除了要同步primary 和backup VM, 还需要同步硬盘状态。
使用非共享磁盘,还需要处理脑裂问题,需要使用backup和primary之外的第三方server, backup 和primary 分开时,拥有多的机器的集群可以上线。
4.2 备份虚拟机上运行磁盘读操作
默认设计中,backup VM 从不在虚拟磁盘读(无论共享磁盘或者非共享磁盘),disk read当做一种input,从logging channel 传输。还有一种设计,是backup 运行磁盘读操作,极大减少logging channel的数据传输。但是会降低速度,backup需要进行读操作,并等待完成。
同时当disk read失败时,还有需要进行额外的操作。primary 读成功,backup失败,那么backup需要一直尝试读,直到成功。primary 读失败, 目标内存必须通过logging channel发送到备份机。因为内存内容不确定,不一定由读成功的备份VM 进行。
此外,使用共享磁盘,且backup 也读的情况,primary读之后,在同一区域很快有一个写操作,那么这个写操作必须delay。这层依赖可以被检测,同时正确处理,但是增加了实现的复杂度。
在5.1中,很多性能测试结果显示,backup 进行读,只会减少1~ 4%的实际app的吞吐量,但是可以有效减少 logging 带宽,因此带宽有限制的情况,在backup VM 进行读操作是很有用的。