笔记: Lecture 4: Primary/Backup Replication
视频:Lecture 4: Primary-Backup Replication
论文地址:The design of a practical system for fault-tolerant virtual machines
课程概要
业界容错的解决方案之一是主备复制,通过学习VMware FT看看具体如何实现,以及主备遇到的问题。
正文
容错的目的
- 保证服务的可用性
- 服务器和网络都会出现故障,但是使用副本容错还是必不可少
复制副本并不是银弹
-
单个副本的容错
风扇停止运行、CPU超载导致主机停机、电源线拔了、光缆被挖。因为磁盘空间不足导致软件停止。
- 硬件缺陷、软件bug、或者是配置错误。这些可以导致一时间所有的副本都宕机。(其实配置问题只需要增加校验的步骤也可以解决)
- 出现地震或者是全城停电。(这里要有异地副本)
复制副本的开销如何?带宽、磁盘、额外的服务器
目前两种主要的复制方式:
-
状态复制
主节点负责执行写、写完之后发送最新的状态给副本
-
复制状态机
客户端发送状态至主节点,主节点按顺序执行并且发送给副本。所有的副本执行相同的动作。相同的开始状态、操作、顺序、最终态状态复制传输比较简单,方式状态可能会比较多,网络传输速度太慢
复制状态机往往用的网络更少,它的特征主要是进行状态比较,但是对于保证正确性需要做很多工作。VM-FT就是使用这个模式
本课重点
- 复制什么状态
- 主节点是否需要等待备节点
- 什么时候进行主备切换?
- 主备切换时异常如何处理?
- 如何快速的进行主备切换?
在生产环境中,主备的同步要到什么程度?
- 应用状态的同步,eg:数据库表。GFS是这种方式,主节点会把高优先级的操作发送给副本(譬如:文件写入。计算机时钟中断则不同步)。应用代码需要理解容错,对于流的新旧要校验
-
机器级别,eg:寄存器和RAM内容都同步
需要我们同步复制主节点所有的操作(中间过程不再加工数据),机器事件也会转发(中断、DMA内容、&c),事件流保持完整同步。除非是机器差异产生的差别。对于指令并不是真正意义上的执行该指令,而是应用通过指令得出最后的结果。这一切是在软件层面完成
VMware FT属于机器级别的状态复制,可以运行在不通架构的服务器和系统之上(兼容),对于客户端来说整体还是单体操作系统,无任何感知保持透明。
论文概览
FT的架构
FT通信协议
术语:
hypervisor==monitor(监控)== VMM(虚拟机监控)
O/S+app指代在虚拟机中运行的应用程序(操作系统、应用软件)
两台机器,一台主,一台副本
主节点通过网络(日志通道log channel)发送所有的外部事件(客户端包)至副本,日志是有顺序的。当主备其中某一个出现故障时,都会变成单机,如果是备会变为主,此时无副本。如果是备出现故障,主的事件会丢失。
VMM会模拟本地磁盘接口,虚拟机操作文件时。与访问实际磁盘的调用一致。但实际上存储在网络存储上,通常只有主和存储服务器通信(副本只是读取),当副本变为主节点时才对存储进行通信。因为是存储在统一的物理磁盘上,在副本出现故障时,新的副本不需要拷贝数据,就能很快的启动。
主节点何时必须像副本发送信息?
当出现可能导致会产生不一致的时候,就需要立即发送(例如文件更新)。任何导致结果不一致的不确定指令也需要同步。
有哪些动作需要FT介入处理?
当内存和寄存器相同时,大多数的指令在主备上各自的结果都一致。但是有些不确定的指令就需要FT处理,例如来自外部的输入事件——网络数据包、DMA数据+中断、时钟中断、非状态指令(读取当前时间、随机数)、多核并行任务的执行(多线程在多次运行时对锁的抢占顺序是会不同)。
当出现主备出现分歧时,会导致什么后果?
副本的b/c状态与主节点的状态不一致,如果此时出现主节点宕机,客户端就会看到数据不一致。
例子:GFS租约过期
假设GFS的master是有副本,chunkserver在租约过期前的60s就发送续期指令。(时钟中断管理服务器时间)
在master上,收到请求后发生时钟中断。此时主节点对chunkserver进行续约
在backup上,时钟中断在请求之前发生,此时副本记录的chunkserver已经过期了。
假设此时主节点崩溃,失效的主节点被副本接管。副本发现之前的chunkserver已经过期了,需要重新选择新的chunkserver。那么此时在系统中就会出现两个chunkserver都持有合法的租约。
因而要求:副本要和主节点所有事件都同步、顺序一致、保持指令流的一致性。
FT的日志包含三部分:指令、类型、数据
FT是如何处理时钟中断的?
理想状态:主备在同一事件流所看到的指令是一致的。
主:
- FT发生时钟中断
- FT从CPU中读取指令编号
- FT发送指令X的时钟中断到日志通道(log channel)
- FT 分发中断给主节点,然后恢复正常
这些依赖CPU需要支持在执行X条指令后发生时钟中断
备:
- 忽略自己的时钟中断
- FT获取所有日志条目之前,未执行的指令
- FT告诉CPU在指令X时,进行中断
- FT模拟计时器中断,进行备份操作
FT是如何处理网络包的(请求包)?
主:
- FT告诉网卡(NIC),拷贝一份数据包到FT的私有回弹缓冲区(bounce buffer)
- NIC有时会执行完DMA后才进行中断
- FT捕获到中断
- FT暂停主节点
- FT复制刚刚第一步存储在bounce buffer的数据到主节点内存
- FT在主节点中模拟NIC中断
- FT发送网络数据包和指令#到副本
备:
- FT从log stream中 获取到数据和指令#
- FT通知副本CPU在指令X处中断
- FT拷贝网络包数据到副本内存中,并且在副本中模拟NIC中断
为什么会引入bounce buffer?
主要是为了数据在主备节点中,能在合适的时间得到处理,而不会接收到数据包就开始处理,不利于回放。
注意:副本需要滞后一个日志记录处理
假设主节点在指令X之后,进来一个中断或者是输入。备份服务器在获得指令X后就开始了执行,那么此时的输入的结果就无法在副本中重放,因为副本的已经执行完了指令X,而新进来的输入或者是中断需要等待下一个指令来结束。(类似文件结束符)
举例:非确定指令
在现实生产环境中,即使主备的状态一致,但是还是会出现相同的指令产生不同的结果。例如:读取当前时间、随机数、处理器序列号、时钟周期
主节点执行指令的流程:
- 主节点执行指令,FT调用CPU执行中断
- FT执行指令并且记录结果
- 发送结果和指令给副本节点
副本节:
- FT读取日志,根据指令生成中断
- FT根据主节点需要的结果返回信息
执行结果响应流程:
- 主备节点执行指令后都会输出结果
- 主节点的输出结果为实际结果
- 备节点的结果会被忽略(只作为主节点返回结果的准许)
执行结果响应案例:数据库服务器
客户端发送“自增”请求给数据库,数据库实行自增后存储数据,并返回新的值给客户端。
- 主节点存储的值是10
- 客户端发起自增请求
- FT分发请求到主备节点
- 主节点增加到11,并响应结果给FT,FT响应回客户端
- 副本节点执行,增加到11,并响应给FT
- 客户端得到结果11
但是:
假设主节点在发送结果后宕机,客户端得到的结果是11
logging channel丢失了客户端的写请求,因为主节点已经宕机不会再次发送
副本会变为主节点,此时副本内的值还是10。
客户端此时发起一个“自增”请求,得到的结果不是12,而是11。
解决方式:改变结果的输出规则(论文2.2)
主节点发送结果之前,必须先收到副本的响应才能发送结果
主节点:
- 收到客户端的自增请求
- 发送客户端请求到logging channel
- 主节点缓存当前结果
- 等待副本响应已经收到日志
- 响应结果给客户端
假设主节点收到副本响应前后在某个时间点宕机:
- 在收到副本响应前宕机
副本是看不到客户端请求的,并且不会自增。主无应答
-
在收到副本响应后宕机
客户端可能看到“11”的响应结果,副本肯定已经收到客户端的写请求。并且值为11
结果响应规则是一个trade off问题,在所有的复制系统中都有可能出现。它会直接影响系统的性能。有时是可以取舍的,例如在等待响应前,结果为只读操作,得到响应后才可以再次修改。而FT是非应用级别响应,这里需要等待副本响应结果。
论文讨论
Q:如果主节点在收到副本节点响应后立即宕机(还未返回给客户端),那么客户端是否永远等待响应结果?
A:当主节点宕机,副本提升为主节点时,会出现以下情况:
- 副本会消化完日志流中的数据
- 消化日志时所产生的输出被丢弃
- 日志消化完后,副本变为主节点,此时结果不再丢弃
在例子里面,最后一条日志是客户端的请求指令,当客户端请求结果时,所看到的值是最新的值,这个结果有新晋升为主节点的副本返回
Q:假设主节点在返回结果后宕机,副本会不会返回两次?
A:这个是有可能的,如果是TCP,那么会收到重复序号的数据包。如果是写磁盘,会再写一份同样的数据到相同的块。
在复制系统中,主副本替换产生两次结果响应是很常见的情景,客户端需要让状态具有幂等性。相同的请求,多次执行结果不变。
Q:假设FT产生的网络分区,是否会导致“脑裂”?如果主节点和副本都假设对方已经宕机,他们是否都变为主节点?
A:共享存储的磁盘服务已经解决了这个问题,磁盘服务支持原子TSL(原子检查并设置)操作,主副节点遇到对象已经宕机,都会试图进行test-and-set操作,如果只存在一个存活,在进行test-and-set后并上线,但是假设两者都试图修改,其中有一方会失败,失败的晋升请求会被忽略。
不过磁盘服务器可能会有单点故障问题,磁盘服务宕机,整个服务也会宕机。这里可能需要引入支持复制的磁盘服务器
Q:为什么不支持多核处理器?
A:并行执行,无法保证能达到机器级别的指令执行结果保持统一
性能(图表1)
FT/非FT:性能差别较小
日志带宽:MySQL的磁盘+网络传输可以达到18Mbits/秒
总体来看,这些结果其实比较偏低。一块SSD磁盘可以达到400Mb/秒,这个数据看起来是这些应用不怎么依赖磁盘
FT适合应用于什么场景?
关键但压力低的服务,例如域名服务器。其软件的修改比较低的服务
吞吐量大的服务如何选择复制?
在工业界,常见使用的复制是应用级别的复制,复制状态机。例如数据库。在数据库中,状态只有DB,而不是这台服务器内存+磁盘的所有数据。对应的事件是get和set操作,而不是数据包和中断。
优势在于更少的颗粒度同步,并且开销也小。GFS使用的是应用级别的复制,Raft也是为应用级别而诞生的
总结
主备复制这个常见,VM-FT讲述的很清晰,适合学习复制是什么。但是FT是单点的,会有单点故障的风险。如果是为了性能,应选用应用级别的复制状态机。
备注
听过VM已经支持了多核CPU,FT已经被废弃。
What’s New in vSphere 6.0: Multi-CPU Fault Tolerance
ReTrace: Collecting Execution Trace with Virtual Machine Deterministic Replay
参考资料