6.824分布式系统[3]-主从复制

准备工作

阅读:Fault-Tolerant Virtual Machines

为什么要阅读这篇文章

  • 了解分布式系统的容错机制
  • 本文是对于容错机制的比较特殊的实现,其并不是要设计一个应用程序级别的容错系统,而是一个系统级别的。需要处理中断,能够为了实现一个容错的虚拟机系统(VM-FT),难度更大。

容错(Fault tolerance)

  • 即使发生故障也会继续提供服务的能力
    一些理想的属性:
  • 可用性:尽管[某些故障]仍然可用
  • 一致性:对于客户端来说就像一台服务器
  • 对用户和软件透明(内部运行机制透明)
  • 高效

我们将尝试解决哪些失败?

  • 失败-停止错误
  • 网络丢包
  • 网络分区

核心思想

  • 容错的核心思想是建立副本,需要两个以上的服务器。
  • 每一个副本都维持相同的状态,如果一个服务器失败,其他服务器可以继续进行。
  • 需要思考的重要问题:
    • 什么状态需要去复制?
    • primary(主服务器)需要等待副本服务器复制完成吗?
    • 什么时候需要切换到副本服务器
    • 转换时是否可见异常?
    • 转换到副本时能否加速?

两种主要的方式

  • 状态转移
    • primary执行操作
    • primary将状态转移到副本
    • 状态转移虽然简单,但是状态可能很大,转移可能很慢
    • 论文中的虚拟机使用了复制状态机。
  • 复制状态机
    • 所有副本执行所有操作
    • 相同的开始状态
    • 相同的操作
    • 相同的顺序
    • 确定性的操作
    • 则具有相同的最终状态
    • 更有效率,但是更复杂

本论文的目标

  • 构建复制状态机
  • Primary和副本具有相同的初始状态(内存,磁盘文件)
  • primary通过日志通道(logging channel)传递给副本服务器
  • 相同的指令、相同的输入、相同的执行

什么时候在主数据库上执行与备份上可能不同?

  • 来自外部的输入(网络)
  • 从存储服务器读取的数据
  • 定时器中断(Timing of interrupts)。 参考:wikibook
  • 一些特殊的指令:循环计数
  • 冲突()

不一致的原因

  • 锁定服务器将锁定授予客户端C1,拒绝来自C2的后续请求
  • 锁定服务器在一分钟后撤消锁定
  • 假设C1持有锁并且,1分钟马上就要到时,c2请求锁。这时,Primary可能会在定时器1分钟发送中断之前立即看到C2的请求,拒绝其请求。副本可能会在定时器1分钟发送中断之后看到C2的请求,同意它。
  • 因此:副本必须在指令流中的同一点以相同的顺序看到相同的事件。

解决定时器中断的解决方案

  • primary
  • FT 收到定时器中断信号
  • FT从CPU读取指令号
  • FT在日志通道(logging channel)上发送的"在指令x处触发计时器中断”
  • FT给primary发送中断信号,然后恢复。
  • Backup
  • 忽略自己的计时器硬件
  • 在副本得到指令X之前,观察是否日志中有需要在这之前执行的日志。
  • FT告诉CPU在指令X处中断
  • FT模拟计时器中断,然后恢复。

解决磁盘、网络数据输入可能不一致的问题

FT拦截,只能够让primary能够访问硬件。

  • Primary:
    • FT通知硬件通过方式将数据存入FT的私有缓存中
    • 在某一时刻,硬件执行DMA,然后中断
    • FT收到中断信号
    • FT暂停primary
    • FT复制缓冲区数据到primary内存中。
    • FT为primary模拟中断,稍后恢复。
    • FT将数据和指令发送到备份
      Backup:
    • FT从日志流中获取数据和指令
    • FT告诉CPU在指令X处中断
    • FT在中断期间复制数据

缓冲区(bounce buffer)的目的就是为了在内存的同一个时间点执行相同的操作,读取相同的数据。

解决特殊的指令

  • Primary:
    • 如果primary执行了特殊的指令,FT会通知CPU中断
    • FT执行指令并记录结果
    • 将结果和指令发送到备份
  • Backup:
    • 副本在执行此指令时也会中断。
    • 副本应用从primary中得到的值。

Output Rule

  • primary必须在副本收到此输出指令的日志后,才能够输出。
  • 此规则是必要的,因为我们的服务是为了在奔溃时让用户是无感知的。
  • 有了此规则,即便peimary奔溃了,副本也能够和primary一样,对于之前的请求返回相同的数据。
    • 假设primary收到请求I1 I2 I3 并输出, 这时primary奔溃,副本只能看到I1,I2。这时 一个之前收到I1,I2,I3的客户端由于切换到副本后,相同的请求就只能看到I1,I2。
  • 增加了延迟,限制了性能。

问 & 答

如果primary收到副本对于I3 ack确认后奔溃,会发生什么?

这时会切换到副本运行,而副本会执行I3命令,并返回给客户端。

如果primary在发出输出之后崩溃了怎么办?

副本会立即接管。
对于TCP传输:接收者将忽略重复的序列号。
对于磁盘:副本将相同的数据写入相同的块。

如果网络分区,primary和副本都认为彼此失活?

共享磁盘只允许唯一的一个primary。

为什么确定性的操作,在物理硬件上比虚拟机上更难?

虚拟机管理程序(hypervisor)模拟和控制硬件的许多操作,这些操作可能会导致primary和副本执行不同。例如定时中断(timing interrupts)

什么是虚拟机管理程序(hypervisor)

管理程序是虚拟机系统的一部分,和虚拟机监视器(VMM)一样。 系统管理程序模拟计算机以及在其中运行的操作系统和程序。
在本文中,primary和副本是运行在虚拟机中的guest操作系统。而FT是实现每个虚拟机的管理程序的一部分。

GFS和VMware FT均提供容错功能,谁更好?

  • FT更底层强大,对内存,网络包和磁盘提供了一种容错能力。可以使用它为所有运行在其上的服务透明地提供容错功能。
  • GFS仅提供存储容错功能。 由于GFS专用于特定的简单服务(存储),因此其复制比FT更有效。 例如,GFS不需要使中断在所有副本上的完全相同的指令处发生。
  • GFS是应用程序级别的具有容错能力的大型应用程序之一。

缓冲区如何帮助避免冲突

网络数据包或请求的磁盘块到达primary并且要复制到primary的内存时,

  • 没有FT,相关硬件将数据复制到内存中,同时 软件正在执行。操作系统指令可以在DMA期间读取该内存。由于冲突,在某一时刻,可能无法看到DMA的数据。因此可能出现由于primary与副本的时间不同,一个能看到,一个不能看到这个数据。

表现

  • logging带宽
    • 直接反应磁盘读取率 + 网络输入率
    • 大约18 Mbit/s for my-sql
  • 比较慢应用程序可以至少400 Mbps的速度读取磁盘
  • 用途
    • 关键但强度较低的服务,例如 名称服务器。
    • 其软件不便于修改的服务。

高吞吐量服务的复制

* 人们将应用程序级复制状态机用于例如 数据库。
* 状态只是DB,而不是全部的内存和磁盘。
* 事件是数据库命令(put或get),而不是数据包和中断。
* 更少的细粒度同步,更少的开销。
* GFS使用应用程序级复制,与lab2相似。

参考资料

讲义
FAQ