MIT6.824 Distributed System 学习笔记 - Introduction

363 阅读7分钟

6.824 Introduction

构建分布式系统的驱动力

  • 需要获得更高的计算性能:大量的并行运算,大量CPU、大量内存、以及大量磁盘在并行的运行。
  • 提供容错(tolerate faults):比如两台计算机运行完全相同的任务,其中一台发生故障,可以切换到另一台。
  • 一些问题天然在空间上是分布的:例如银行间转账,银行A在纽约有一台服务器,银行B在伦敦有一台服务器
  • 担心安全问题,我们把系统分成多个的计算机,这样可以限制出错域:比如有一些代码并不被信任,但是你又需要和它进行交互,你不想要信任这些代码,所以你的代码在另一台计算机运行,我的代码在我的计算机上运行,我们通过一些特定的网络协议通信。

挑战

  • 并发编程和各种复杂交互所带来的问题
  • 局部错误:分布式系统有多个组成部分,再加上计算机网络,你会会遇到一些意想不到的故障。
  • 性能

基础架构

基础架构的类型主要是存储,通信(网络)和计算。

对于存储和计算,我们的目标是为了能够设计一些简单接口,让第三方应用能够使用这些分布式的存储和计算,它看起来就像一个非分布式存储和计算系统一样(尽管这几乎是无法实现的梦想),但是实际上又是一个有极高的性能和容错性的分布式系统。在这些基础架构之上,构建第三方应用程序。

实现工具

人们在构建分布系统时,使用了很多的工具,例如:

  • RPC(Remote Procedure Call)。RPC的目标就是掩盖我们正在不可靠网络上通信的事实。
  • 线程。使得我们可以利用多核计算机
  • 因为我们会经常用到线程,我们需要在实现的层面上考虑并发控制,比如锁。

性能

可扩展性 Scalability

如果我用一台计算机解决了一些问题,当我买了第二台计算机,我只需要一半的时间就可以解决这些问题,或者说每分钟可以解决两倍数量的问题。两台计算机构成的系统如果有两倍性能或者吞吐,就是可扩展性。

假设我们建立了一个常规网站,一般来说一个网站有一个 HTTP服务器,还有一些用户和浏览器,用户与一个基于Python或者PHP的web服务器通信,web服务器进而跟一些数据库进行交互。

当你只有1-2个用户时,一台计算机就可以运行web服务器和数据,或者一台计算机运行web服务器,一台计算机运行数据库。

你该怎么修改你的网站,使它能够在一台计算机上支持一亿个用户?可以购买更多的web服务器,然后把不同用户分到不同服务器上。这样,一部分用户可以去访问第一台web服务器,另一部分去访问第二台web服务器。所有的web服务器都与后端数据库通信。

但是这种可扩展性并不是无限的。很可能在某个时间点你有了10台,20台,甚至100台web服务器,它们都在和同一个数据库通信。现在,数据库突然成为了瓶颈,并且增加更多的web服务器都无济于事了。单个数据库或者存储服务器不能支撑这样规模的网站,所以才需要分布式存储。

可用性 Availability

容错特性的一种,另一种是可恢复性recoverability,是一个比可用性更弱的需求。

大型分布式系统中有一个大问题,那就是一些很罕见的问题会被放大。例如在我们的1000台计算机的集群中,总是有故障,在一个有1000台计算机的网络中,会有大量的网络电缆和网络交换机,也经常有故障。大规模系统会将一些几乎不可能并且你不需要考虑的问题,变成一个持续不断的问题。

必须要在设计时就考虑,系统能够屏蔽错误,或者说能够在出错时继续运行。我们需要为第三方应用开发人员提供方便的抽象接口,尽可能多的对应用开发人员屏蔽和掩盖错误。

可恢复性(recoverability):对于一个具备可用性的系统,为了让系统在实际中具备应用意义,也需要具备可恢复性。因为可用的系统仅仅是在一定的故障范围内才可用,如果故障太多,可用系统也会停止工作,停止一切响应。但是当足够的故障被修复之后,系统还是需要能继续工作。所以,一个好的可用的系统,某种程度上应该也是可恢复的。当出现太多故障时,系统会停止响应,但是修复之后依然能正确运行。这是我们期望看到的。

为了实现可用性和可恢复性,有很多工具。其中最重要的有两个:

  • 非易失存储(non-volatile storage,类似于硬盘)。我们可以存放一些checkpoint或者系统状态的log在这些存储中,当电力恢复,我们还是可以从硬盘中读出系统最新的状态,并从那个状态继续运行。但构建一个高性能,容错的系统,聪明的做法是避免频繁的写入非易失存储,因为很慢。
  • 复制(replication)。任何一个多副本系统中,都会有一个关键的问题:比如我们有两台服务器,它们本来应该是有着相同的系统状态,但这两个副本总是会意外的偏离同步的状态,而不再互为副本。

一致性

例:假设我们在构建一个分布式存储系统,并且这是一个KV服务。

在一个分布式系统中,由于复制或者缓存,数据可能存在于多个副本当中,于是就有了多个不同版本的key-value对。假设服务器有两个副本,那么他们都有一个key-value表单,两个表单中key 1对应的值都是20。

现在某个客户端发送了一个put请求,并希望将key 1改成值21,这个put请求发送给了第一台服务器。之后会发送给第二台服务器,因为相同的put请求需要发送给两个副本,这样这两个副本才能保持同步。

但是就在客户端准备给第二台服务器发送相同请求时,这个客户端故障了,现在我们处于一个不好的状态,我们发送了一个put请求,更新了一个副本的值是21,但是另一个副本的值仍然是20。

如果现在某人通过get读取key为1的值,那么他可能获得21,也可能获得20,取决于get请求发送到了哪个服务器。

强一致性:比如get请求可以得到最近一次完成的put请求写入的值。但分布式系统的各个组件需要做大量的通信,才能实现强一致性。

弱一致性:可以得到旧的数据,为了让弱一致更有实际意义,人们还会定义更多的规则。人们常常会使用弱一致系统,你只需要更新最近的数据副本,并且只需要从最近的副本获取数据。