[7][lecture] Lecture 4:VMware fault-tolerant virtual machines

6.824 2018 Lecture 4: Primary/Backup Replication

  • VMware FT,一个极端例子下的主备复制
  • 容错,即使出错也可以继续提供服务,应该具备以下条件:第一部分组件失效仍然可用;第二对外隐藏分布式,提供单机一样的一致性;第三,对客户端开发友好透明,对server开发友好透明;第四,性能足够好
  • 可以处理哪些失效?Fail-Stop类型的失效,独立的失效,网络丢包,网络分区
  • 无法处理的失效?执行出错但是不崩溃,人为因素,级联失效
  • 容错对外的表现?某些机器挂掉依旧对外可用;网络失去连接,wait;多数机器挂掉,服务失效;
  • 容错的主要方案:复制,主备或者更多,少数失效,依旧提供服务
  • lab 1实现方案中,worker实现了容错,挂掉不影响服务;但是master依旧是单点,我们是否可以将master也复制,考虑需要复制的状态,worker信息,job的状态追踪,网络连接,cpu寄存器,内存堆栈保存等等
  • 几个有意义的问题?哪些状态需要复制、主节点是否需要等待从节点完成后返回、何时切换到备节点、主备切换过程是否中断服务,是否会有不一致、备节点切换为主节点后如何快速达到最新的状态?
  • 几个有意义的方案:方案一,状态迁移,主节点提供服务并把状态更新到备节点;方案二,复制状态机,每个复制集节点都执行所有op,从初始状态,按照一致的顺序执行一系列op,那么最终状态就是确定且一致的,same start,same ops,same order,确定性执行,就可以得到一致的最终状态;第一个方案比较简单,不过整个状态是巨大的,复制代价高;VM-FT使用方案二,性能上更好,增量复制优于全量复制,不过正确的复制需要一些技巧,这些技巧广泛应用在lab 2 3 4中
  • 如何定义复制状态机?在什么层面定义状态复制?比如对于KV的put和get来说,可以在应用层面进行复制和定义,将高level的op(client的get和put)在主从之间复制,比较容易实现;也可以在x86指令层面,低层级的复制使得对任何应用都可以进行状态机复制,不过要处理的东西很多,比如中断,DMA,多变的x86指令

论文讲述的就是指令集层面的复制,虚拟机层面的主备复制,是一个非常宏伟的系统

目标是:第一,基于vm可以做到对已有的所有软件提供ft;第二,客户端无感知;第三,现有软件无需任何改动即可得到高可用

架构设计:通过hypervisor监控所有对VM的操作,os和app跑在vm中,主备vm,共享disk存储,主节点提供服务同时把所有的input通过log channel同步到备节点;方案属于复制状态机方案,主备节点初始状态一致,包括磁盘和内存,将同样的指令,input作为操作同步,最终的状态保持一致

难点,主备何时会出现分歧?外部输入,时间片轮转中断,disk read时机和顺序,并发竞争,以及有状态的计算过程。

外部输入举例来说,输入顺序到达主备不一致导致的不一致,锁服务,结论就是备节点必须和主节点看到相同的事件,执行顺序。

时间片轮转举例,主节点需要有感知时间片轮转的能力,通过log传递给备节点,备节点的时间片不能由硬件控制,需要通过FT的log channel来控制保证和主节点一致,FT感知后出发cpu时间片中断,然后FT来让备节点重新开始运转

外部存储举例,FT感知中断,忽略备节点的请求,将真实io请求给到主节点;ft告知硬件dma操作,到ft私有buffer,硬件读取结束后中断,ft拦截该中断,ft暂停主节点,将私有buffer数据拷贝到主存,ft模拟中断给主节点读取完成,并继续主节点运行,主节点开始读取,并将数据和指令同步给备节点;备节点,ft感知同步过来的数据和指令,ft触发中断,ftcopy数据执行完成后,继续备节点运行;如此费力模拟中断的原因是,为了保证数据到达主存后,主节点和备节点执行的指令流是一致的

注意备节点始终会比主节点慢最少一个entry,备节点需要看到下一条entry到达后才能安全的执行当前的entry,依旧是为了保障一致性

即便如此,依旧有些有状态操作?比如获取计数器或者时间戳之类的操作,如何应对?主节点,ft感知这样的指令后后触发中断,ft执行指令得到结果,ft将结果直接发送给备节点;备节点,ft感知到这类操作后,中断备节点,然后从log中得到执行结果

Output Rule?主节点需要通知备节点何时产生output,主节点在备节点返回后才能output,依旧是为了一致性,全部写入才能对外可见。VM FT对应用层没有了解,因此一定要保守,所以性能会差一些;如果在应用层面获取更多信息,比如只读操作,那么就可以不用等到备节点返回,从而提高性能

主节点如果在output之间挂了?备节点接收到的话,备节点切换为主后,执行最后一条log,会继续output,如果备节点也没收到,主节点就挂了,此时备节点也不会output,系统是具有一致性的。

主节点output之后挂了,备节点切换为主节点后,仍旧会output,对于tcp协议来说,问题不大,tcp协议具备重传检测机制利用序列号;对于共享存储的操作,也没问题,因为会在同样的位置写相同的数据,最终依旧是一致的。注意到主备切换过程中,出现重复的output比较常见,要区别对待不同的应用,看是否可以接受,比如金融系统就需要慎重考虑

如何处理网络分区,是否会出现脑裂,双写导致不一致?不会,共享的磁盘存储提供test-and-set机制,保证同一时刻只有一个主节点对外服务,不过也因此共享存储是系统的单点,存在失效的可能性,如果需要高可用,存储也需要复制集系统

性能如何

测试结果看,性能损失很小,测试的workload,disk read 400M/s,并不是数据密集型应用;考虑到数据密集型的应用,性能损耗估计很很大,此时可以考虑应用级别的复制状态机实现应用层的复制,复制的状态就可以仅限于db,而不是所有memory和disk,复制的op就是db的command,类似bin log,而不是所有的中断和网络报文,减少overhead,提高性能

结论

  • 主备复制集方案,VM-FT提供了一个极端底层的例子
  • 如何处理脑裂,网络分区和双写,raft提供解决方案
  • 如何提高性能?应用层面的replica-state-machine

FAQ

Q: 为什么物理机比虚拟机难?

A: vm中hypervisor提供了精准的模拟和控制,比如何时发生时间片中断,而在物理机上,几乎就是纯随机事件,无法掌控

Q: GFS和ft都提供容错,有何不同?

A: ft提供更底层的,只要是网络服务可以跑在虚拟机中,就可以通过ft提供容错。gfs则是应用层面的,仅针对存储系统来容错,效率更高,但是不通用。

Q: bounce buffer如何避免竞争?

A: 网络包或者内存dma操作,如果不去控制,guest同一时刻读取可能会读到也可能读不到,主节点和从节点正好在dma前后执行,就会造成分歧;处理方法是,ft将网络包或者内存先拷贝到自己的buffer中,然后中断主节点和从节点,将buffer拷贝到guest主存后,在继续执行,精密的保证执行顺序

Q: 随机数可以确定吗?

A: 可以,hypervisor精确控制vm内部的一切

Q: IO中断如何处理?

A: 如果log中有disk io成功的标识,那么备节点正常执行即可;如果没有,这次IO就需要重新开始

Q: 容错只针对fail-stop类型有实际意义吗?

A: 有的,真实世界绝大部分错误是fail-stop类型的,比如网络中断,断电,系统crash。对于人为的攻击,以及大量non-fail-stop类型的错误,被称为拜占庭问题,这类问题有解决办法,当然主要是依赖复制和通信达成共识,6.824课程中几乎不涉及这类问题,会在课程最后简单介绍

你可能感兴趣的:(分布式)