文字记录 · CC BY 3.0

MIT 6.824 讲座 1:分布式系统 & MapReduce

本页标题、字幕、摘要和阅读笔记为已保存的 AI 译文,可能有误。时间戳与来源一致,可展开查看原始字幕,并对照原视频核对。

MIT 6.824 讲座 1:为什么要构建分布式系统、实验课如何运作、容错与一致性,以及一次对 Google MapReduce 的讲解。

MIT 6.824:分布式系统 · 发布于 · 1小时20分钟 · 英语 · 许可证:CC BY 3.0 · 来源:在YouTube上观看

转录来源:Vidleaf上的自动语音识别(可能包含错误)。AI标点由Vidleaf添加;保留原始措辞和时间戳锚点。原始转录可在下方获取。

AI生成的摘要

MIT 的分布式系统入门讲座解释了为什么应用要使用协作的计算机,以及这样做为何会带来困难的设计问题。性能、容错和物理分布是该领域的动机,而并发和部分失败使实现变得复杂。讲座概述了课程和实验课,然后展开关于存储、复制、可扩展性和一致性的想法。Google 的 MapReduce 作为案例研究,将简单的 map 和 reduce 函数与分发工作和移动数据所需的基础设施联系起来。带时间戳的章节使人们能够跟随从一般设计权衡到具体词频统计和网络示例的过渡。

要点

  • [0:17] 分布式系统协调联网计算机来执行一项连贯的任务。
  • [42:39] 一致性选择会影响读者可能观察到什么,以及副本之间协调的成本。
  • [46:53] MapReduce 将讲座的设计思想与一个用于大型分布式计算的框架联系起来。

根据文字记录生成。请对照原始视频核查所链接的段落。简要说明和要点由 Vidleaf 于 2026-10-21 审核。

完整概述

本讲座开启一门分布式系统课程,将分布式系统定义为通过网络通信、协作完成一项连贯任务的计算机,并通过并行带来的性能、容错、物理分布和安全性来阐明该领域的动机。它主张,能在单台计算机上解决的问题就应该那样解决,而分布式系统之所以困难,是因为并发执行和部分失败。讲师介绍了课程安排:一个包含实验课、日程和 Piazza 的课程网站;由 Robert Morris 主讲的讲座,配有四名助教;几乎每节课都有一篇论文;两次考试;四个编程实验课,从 MapReduce 逐步推进到基于 Raft 的复制、一个可复制的容错键值服务器以及分片;以及一个可选期末项目,可替代其中一个实验课。实验课按通过多少给定测试评分,没有隐藏测试,并建议学生尽早开始,利用助教答疑时间和 Piazza。课程涵盖应用的基础设施——存储、通信和计算——以存储为主要焦点,并有一个反复出现的目标:用抽象隐藏这些系统的分布式本质。讲座随后涵盖实现思路,如远程过程调用、线程和锁,以及设计挑战,包括可扩展性(在大概 10、20 或 100 个 Web 服务器之后,数据库成为瓶颈)、大规模容错、非易失性存储、复制和一致性,并指出强一致性代价高昂,副本应具有独立、不相关的故障概率。它解释说,副本被放置在相距很远的地方,但光速传播意味着跨大陆通信可能需要几毫秒或几十毫秒,因此人们常常构建较弱的系统,只更新或查询最近的副本。MapReduce 作为案例研究呈现:由 Google 构建,并有一篇 2004 论文,用于处理数 TB 数据的巨大计算,让非专家只编写 map 和 reduce 函数,采用主节点和工作节点架构,输入和输出为 GFS 上的文件,并有一个词频统计示例。由于 GFS 服务器和 MapReduce 工作节点运行在同一批机器上,map 默认可以从本地磁盘读取输入,但 shuffle 会将每一条数据跨网络移动,而这正是昂贵的部分。讲者指出,现代数据中心网络的吞吐量要高得多,据称 Google 几年前已停止使用 MapReduce,而后来的 MapReduce 不再尝试在数据存储的位置运行 map;该片段最后宣布了一个涉及某种简化版 MapReduce 的实验课。

带时间戳的章节摘要

分布式系统:定义与动机

  • [0:17] 分布式系统是一组通过网络通信、协作完成某项连贯任务的计算机。
  • [0:32] 课程案例研究包括大型网站的存储、MapReduce 等大数据计算,以及点对点文件共享。
  • [1:10] 如果一个问题有可能在单台计算机上解决,你就应该那样做,因为分布式系统并不更简单。
  • [1:40] 构建分布式系统的一个原因是通过跨许多 CPU、内存和磁盘臂的并行来获得高性能。
  • [1:54] 另一个原因是容错,例如让两台计算机做完全相同的事情,以便其中一台失败时另一台可以接管。
  • [2:11] 有些问题在空间上天然分散,例如纽约市和伦敦的计算机之间的银行间转账。
  • [2:38] 最后一个原因是安全性:将计算拆分到多台计算机上,使不受信任或有缺陷的代码被隔离,并且只通过定义狭窄的网络协议通信。
  • [3:20] 课程大部分聚焦于性能和容错,不过安全性和物理分布常常通过案例研究的约束进入讨论。
  • [3:32] 分布式系统之所以困难,部分原因在于跨多台计算机的并发执行带来了复杂的交互和奇怪的时序相关问题。
  • [4:12] 它们之所以困难,还因为多个部件加上网络会导致部分故障,即某些部件停止工作而其他部件继续运行,或者网络中断或不可靠。
  • [4:49] 用一千台计算机获得一千倍的加速是很棘手的,通常需要精心设计才能获得你觉得自己应得的性能。

为什么要选修分布式系统课程

  • [5:31] 这门课程值得选修,因为其中的问题和解决方案在技术上既有趣又困难。
  • [5:41] 有些问题从其他问题中已知有相当不错的解决方案,但这些方案在这里并不那么理想。
  • [5:46] 分布式系统被许多现实世界的系统所使用,通常是拥有大量计算机的大型网站。
  • [6:02] 课程刚开始时,分布式系统还算是学术上的好奇之物,有时在小规模上使用。
  • [6:13] 尤其是在巨型网站兴起的推动下,分布式系统在过去 20 年里已成为计算基础设施中极其重要的一部分。
  • [6:36] 人们对此投入了大量关注,但仍有许多未解决的问题留给研究生或对研究感兴趣的人。
  • [6:49] 这门课程适合喜欢动手构建东西的人,通过一系列实验构建相当真实的分布式系统,重点关注性能和容错。

课程结构与后勤

  • [7:17] 课程网站可以通过谷歌找到,上面有实验作业、课程安排以及用于问答的 Piazza。
  • [7:33] Robert Morris 负责授课,四位助教主持答疑时间,并且是解决实验问题的专家。
  • [7:59] 课程组成部分包括讲座、几乎每讲一篇论文、两次考试、编程实验,以及一个可选期末项目,可以替代其中一个实验。
  • [8:35] 讲座涵盖分布式系统中的重要思想,有些讲座涉及实验编程,许多是描述真实问题真实解决方案的论文案例研究。
  • [9:05] 讲座会被录像,授课教师希望将其发布到网上,供复习或未能到场的人使用。
  • [9:18] 每周有一篇论文需要阅读,大多是研究论文,有些是经典如 MapReduce,有些则较新。
  • [9:43] 讲座会梳理出论文中的基本问题和思想,有时涵盖实现细节,并花时间评估容错性和性能。
  • [10:15] 学生应在课前阅读论文,因为讲座无法既解释所有论文内容又对其进行反思;课程旨在教授快速、高效的论文阅读。
  • [10:50] 对于每篇论文,学生必须在前一天午夜之前在网站上提交一个答案和一个问题,这也为教师备课提供了材料。
  • [11:21] 春假前最后一节课左右有一次课堂期中考试,期末考试周有一次期末考试,主要侧重于论文和实验。
  • [11:48] 过去 20 年的旧考试和答案可供备考使用,题目难免与往年相似。
  • [12:12] 有四个编程实验;第一个是简单的 MapReduce 实验,下周五截止。

实验序列、项目和评分

  • [12:38] 实验 2 使用 Raft 技术,理论上通过复制使任何系统具有容错性,Raft 管理复制并在复制的服务器故障时自动切换。
  • [13:07] 实验 3 使用 Raft 实现来构建一个复制的、容错的键值服务器。
  • [13:22] 实验 4 将复制的键值服务器克隆成多个独立组,并将数据拆分到这些组中以实现并行加速,在服务器加入和离开时移动数据块。
  • [14:02] 分片意味着将数据拆分或分区到多个服务器上以获得并行加速。
  • [14:13] 学生可以选择不做实验 4,而是自己做一个关于分布式系统想法的项目,构建一些东西并衡量其是否有效。
  • [14:36] 项目必须以两到三人的团队完成,项目想法必须发送给教师审批并可能获得建议。
  • [15:03] 做项目的学生应进行设计工作,构建一个真实系统,在课程最后一天进行演示,并提交一份简短的书面报告。
  • [15:40] 实验成绩基于通过多少测试;所有测试都会给出,因此没有隐藏测试,本地通过所有测试很可能意味着满分。
  • [16:18] 调试实验可能很耗时,因为分布式系统有大量并发和通信,所以学生应尽早开始并利用助教答疑时间和 Piazza。

应用基础设施课程

  • [17:34] 这门课程是关于应用程序的基础设施。
  • [17:38] 课程分为他人(客户)编写的应用程序和正在研究的基础设施两部分。
  • [17:49] 应用程序将使用本课程讨论的基础设施。
  • [18:05] 常见的基础设施类型有存储、通信和计算。
  • [18:15] 课程将涵盖提供所有三种基础设施的系统。

课程重点:存储、计算、通信

  • [18:23] 存储将是主要焦点,因为它是一个定义明确且有用的抽象。
  • [18:31] 存储抽象通常相当直接,因此人们对构建复制的、容错的、高性能的分布式存储了解很多。
  • [18:45] 课程还将涵盖诸如 MapReduce 之类的计算系统。
  • [18:53] 通信将主要作为构建分布式系统所需的工具来介绍,因为本课程主要是通信的使用者。
  • [19:11] 学习通信系统本身更多是6829的主题。
  • [19:24] 对于存储和计算,很多目标是发现能简化接口的抽象,使应用程序易于在其上构建。
  • [19:41] 这意味着构建隐藏这些系统分布式特性的抽象。
  • [19:50] 这个梦想(很少完全实现)是提供一个对应用程序来说看起来像非分布式存储系统(如文件系统)的接口。
  • [20:37] 本课程只走了一部分路:分布式存储或计算的抽象很少能表现得和非分布式版本完全一样。

分布式系统中的实现主题

  • [21:11] 所涵盖系统中一个反复出现的一般主题是实现。
  • [21:27] 远程过程调用是学习构建这些系统的常用工具,其目标是掩盖不可靠网络上的通信。
  • [21:45] 线程是另一个实现主题:一种利用多核计算机的编程技术,对本课程更重要的是,一种组织并发操作的方式,有望简化程序员的视图。
  • [22:08] 由于线程将被大量使用,课程还需要花时间在实现层面的并发控制上,例如锁。
  • [22:22] 这些实现思想将在许多论文中涉及,但将在实验室中大量出现,学生将在那里构建分布式系统。

分布式系统中的可扩展性和瓶颈

  • [23:03] 分布式系统的高层目标通常是可扩展的加速。
  • [23:17] 可扩展性意味着将计算机数量翻倍可以将时间减半或将吞吐量翻倍。
  • [23:58] 按比例扩展以获得该比例的吞吐量是一个巨大的胜利。
  • [24:17] 花钱购买计算机比支付程序员重构软件以提高性能更便宜。
  • [25:10] 需要精心设计才能从许多计算机实际获得相应的性能。
  • [26:27] 典型的第一步是购买更多Web服务器并将用户分散到它们上面。
  • [27:18] 这种可扩展性很少是无限的;在10、20或100台Web服务器之后,数据库成为瓶颈。
  • [27:51] 添加Web服务器将瓶颈从Web服务器转移到数据库。
  • [28:01] 此时几乎肯定需要设计工作,因为重构单个数据库很少是简单的。

横向扩展和容错

  • [28:15] 在单个数据库中排序的数据可以重构为拆分到多个数据库。
  • [28:24] 这种重构通常需要相当多的工作且很别扭,但许多人实际上需要这样做。
  • [28:31] 课程将展示许多例子,其中讨论的分布式系统是存储系统。
  • [28:39] 这些例子来自运行类似大型网站的作者,他们在单个数据库或存储服务器上耗尽了资源。
  • [28:49] 以这种方式扩展的系统是可取的,但很难或需要设计工作才能将这个想法无限推进。
  • [29:09] 容错是另一个经常出现的大主题。

大规模容错

  • [29:23] 单台计算机及其操作系统通常可以持续运行数年,而且建筑电源显然是可靠的。
  • [29:46] 对于数千台计算机,即使每台持续运行约一年,一千台机器意味着每天大约三次故障。
  • [30:01] 大型分布式系统将非常罕见的容错问题转变为一直发生的故障。
  • [30:14] 在一个有一千台计算机的系统中,几乎总是有东西坏了,包括崩溃或运行不正确的机器。
  • [30:25] 对于许多网络电缆和交换机,在这个建筑大小的系统中总会有某处电缆或交换机问题。
  • [30:58] 掩盖故障和感知故障的能力必须内置到设计中,因为故障总是存在。
  • [31:10] 基础设施应向应用程序员隐藏或掩盖故障,这样每个人都不需要为每种故障类型准备复杂的说明。
  • [31:45] 容错的一个常见概念是可用性:在某些类型的故障下(不是所有),系统继续提供未受损的服务。
  • [32:21] 具有两个副本的复制服务可能在一个副本失败时继续运行,但如果两个都失败则不行。
  • [32:56] 可恢复性是比可用性更弱的要求:服务可能停止响应并等待修复,然后像什么都没发生一样继续。
  • [33:38] 可恢复系统通常需要将其最新数据保存在磁盘上,以便在电源恢复后检索。
  • [33:52] 可用系统通常被指定为在发生一定数量的故障之前工作,然后停止,并在修复足够后正确继续。

解决问题的方法

  • [34:35] 演讲者强调了他们喜欢听到并希望获得的内容。
  • [34:40] 将介绍多种解决这些问题的方法,包括最大的锤子。

容错工具:存储和复制

  • [34:49] 非易失性存储是该部门最重要的容错工具之一。
  • [34:54] 在崩溃或电源故障后,非易失性存储(如硬盘驱动器、闪存或SSD)可以存储系统状态的检查点或日志。
  • [35:15] 当电源恢复时,系统可以从硬盘读取其最新状态并从那里继续。
  • [35:28] 管理非易失性存储经常出现,因为更新它往往很昂贵。
  • [35:35] 构建高性能容错系统的许多工作都涉及巧妙的方法来避免过多地写入非易失性存储。
  • [35:50] 传统上,写入非易失性存储意味着移动磁盘臂并等待盘片旋转,这两者在3千兆赫微处理器的尺度下都慢得令人痛苦。
  • [36:05] 闪存要好得多,但仍然需要大量思考才能从中获得良好性能。
  • [36:12] 复制是容错的另一个重要工具,而管理复制副本很棘手。
  • [36:33] 任何复制系统中的关键问题是,两个副本会意外失去同步,不再成为副本。
  • [36:50] 实验2是关于为容错管理复制副本的,这相当复杂。

分布式键值系统中的一致性

  • [37:16] 分布式键值存储系统支持对键和值表进行 put 和 get 操作。
  • [38:08] 应用程序员需要一个描述 put 和 get 含义的规范,否则编写应用程序会很困难。
  • [38:37] 一致性在分布式系统中很有趣,因为为了性能和容错,我们经常保留多份数据副本。
  • [38:53] 在单服务器非分布式系统中,put 和 get 的含义通常相对没有歧义。
  • [39:16] 通过复制或缓存,一个键值对可能有许多版本在四处浮动。
  • [40:19] 如果客户端在更新一个副本之后、更新第二个副本之前崩溃,一个副本保存21,另一个仍然保存20。
  • [40:39] 后续的 get 可能返回21或20,取决于它与哪个服务器通信,并且过时的副本可能在某天暴露出来。
  • [41:28] 由于这种复制危险,关于 put 和 get 的规则需要被写下来。
  • [41:37] 一致性有许多可能的定义;强一致性通常定义为 get 产生最近完成的 put 所写入的值。
  • [42:02] 构建弱一致性系统也非常有用,这些系统不保证 get 能看到最近 put 写入的值。

弱一致性与强一致性的权衡

  • [42:39] 在弱一致性下,读者可能看不到 put,并且可能在无界的时间内看到旧值。
  • [42:54] 强一致性意味着读取保证能看到最近的写入,但这是一个实现起来非常昂贵的规范。
  • [43:19] 多副本的强一致性意味着写入者、读者或两者都必须咨询每个副本,读取一个值需要大量通信。
  • [43:53] 为了避免通信,尤其是当副本相距很远时,人们构建弱系统,可能允许读取旧值的过时读取。
  • [44:23] 为了容错,副本应具有独立、不相关的故障概率,因此将两个副本放在同一个机架中可能是个坏主意。
  • [44:57] 人们希望将副本放置得尽可能远,例如在不同的城市,这样一次地震不太可能摧毁两者。
  • [45:24] 光传播意味着跨大陆与数据中心通信可能需要毫秒或几十毫秒量级的时间。
  • [45:48] 强一致性可能需要等待10、20或30毫秒来与两个副本通信,浪费许多潜在的指令。
  • [46:12] 人们经常构建弱得多的系统,允许只更新或只咨询最近的副本。

MapReduce 作为案例研究

  • [46:53] MapReduce 是一个详细的案例研究,说明了所讨论的大部分思想。
  • [47:06] MapReduce 最初由 Google 设计、构建和使用,论文可追溯到2004。
  • [47:15] Google 面临对数 TB 数据的巨大计算,例如索引网络或分析链接结构以找到重要页面。
  • [47:53] 在单台计算机上对整个网络内容进行排序需要数周、数月或数年。
  • [48:02] Google 希望在数千台计算机上运行巨型计算,以便作业能快速完成。
  • [48:25] 有一段时间,工程师手写一次性软件来将计算分发到许多计算机上。
  • [49:49] 他们想要一个框架,使非专家也能轻松编写和运行巨型分布式计算。
  • [50:04] 程序员只编写一个简单的 map 函数和一个简单的 reduce 函数,而无需了解分布。
  • [50:28] 输入被分割成块或文件,框架并行地在每个输入文件上运行 map 函数。
  • [51:31] map 函数以文件为输入,并产生键值对列表作为输出。
  • [51:45] 在一个单词计数示例中,map 函数将每个单词作为键发出,并将一作为值。

MapReduce 作业执行和术语

  • [52:20] Map 任务为其输入中发现的每个单词发出键值对,例如 A:1 和 B:1。
  • [52:52] 在所有输入文件上运行所有 map 会产生中间输出,即每个 map 一组键值对。
  • [53:06] MapReduce 框架从所有 map 中收集每个键的所有实例,并将它们交给程序员定义的 reduce 函数的一次调用。
  • [53:35] 收集像 B 这样的键需要真正的数据移动,因为它们是由不同计算机上的不同 map 调用产生的。
  • [54:05] 框架为任何 map 输出中出现的每个键安排一次 reduce 调用。
  • [54:17] 在单词计数示例中,每个 reduce 只计算传递给它的项目数,因为每个值都是加一。
  • [55:07] 整个计算称为作业,任何一次 map 或 reduce 的调用称为任务。

MapReduce 单词计数示例

  • [55:27] 单词计数示例说明了 map 和 reduce 函数的样子。
  • [55:40] map 函数接受一个键和一个值作为参数,并用像 C++ 或 Java 这样的普通编程语言编写。
  • [55:53] 用于单词计数的 map 函数将值(即输入文件的内容)拆分成单词。
  • [56:30] 对于每个单词,map 函数将该单词作为键,并将字符串 one 作为值发出。
  • [56:51] MapReduce 中的单词计数 map 函数实际上可以就这么简单。
  • [57:00] map 函数对分布、多台计算机或跨网络移动数据一无所知。
  • [57:18] reduce 被调用时,会传入一个键以及该键对应的所有 map 输出值的向量。
  • [57:37] 对于单词计数,键是单词,值全是一;只有计数重要。
  • [57:44] reduce 发出数组的长度作为该键的最终输出值。
  • [58:00] MapReduce 中的 reduce 函数极其简单,不需要了解容错机制。

链式 MapReduce 作业及其限制

  • [58:34] 你可以将 reducer 的输出馈送到另一个 MapReduce 作业中。
  • [58:51] 在 MapReduce 用户中,为多阶段分析或迭代算法而链接作业是常规做法。
  • [59:08] PageRank 是 Google 用来估计网页重要性的算法,它是一种逐步收敛的迭代算法。
  • [59:25] 在 MapReduce 中实现 PageRank 需要多次运行作业,每次输出都用作另一个作业的输入。
  • [59:50] 你需要设置 reduce 函数以生成下一个 MapReduce 作业所需格式的数据。
  • [1:00:07] MapReduce 的一个缺点是,只有当算法容易表达为 map、按键 shuffle、然后 reduce 时,它才能很好地工作。
  • [1:00:30] 每个 map 必须完全独立,并且是一个只查看其参数的纯函数式函数。
  • [1:00:46] 许多人想要更长的管道,包含多种处理,这必须由多个不同的 MapReduce 作业拼凑而成。
  • [1:00:59] 本课程后面讨论的更高级系统更擅长让你指定完整的管道并进行优化。

MapReduce:程序员视角 vs. 框架视角

  • [1:01:39] 从程序员的角度来看,MapReduce 只涉及 map 和 reduce。
  • [1:01:43] 从框架的角度来看,它涉及作为 MapReduce 框架一部分的工作进程和工作服务器,以及许多其他方面。
  • [1:02:00] 框架的组织非常重要,而程序员的视角则是剥离了分布式部分。

MapReduce 的 emit 与工作架构

  • [1:02:31] 有两个独立的问题:发出的数据会发生什么,以及函数在哪里运行。
  • [1:02:51] 在现实世界中,有一个大型的工作服务器集合,加上一个组织计算的主服务器,如论文中的图一所示。
  • [1:03:16] 主服务器知道输入文件的数量(例如 5,000),并将 map 调用分配给不同的工作服务器。
  • [1:03:39] 工作进程实现 emit,每次 map 调用 emit 时,工作进程将数据写入其本地磁盘上的文件。
  • [1:04:27] 在 map 阶段结束时,每个工作机器持有在其上运行的任何 map 的输出。
  • [1:04:40] 然后 MapReduce 工作进程将数据移动到 reduce 所需的位置。
  • [1:05:13] 在 reduce 运行之前,reduce 工作进程通常必须联系所有其他服务器,并获取它负责的键的所有实例。
  • [1:05:48] 一旦 reduce 工作进程收集了所有数据,它就可以调用 reduce,而 reduce 会调用 reduce emit。

GFS 与 MapReduce 输入存储

  • [1:06:17] 演讲者尚未提到输入和输出数据存储在哪里。
  • [1:06:22] 输入和输出都存储在文件中。
  • [1:06:27] 在任何工作服务器上读取任何输入片段都需要一个网络文件系统来存储输入数据。
  • [1:06:41] 论文讨论了 GFS,即 Google 文件系统。
  • [1:06:49] GFS 是一个集群文件系统,运行在运行 MapReduce 的完全相同的工作服务器上。
  • [1:07:03] GFS 自动将存储在其上的任何大文件分割成 64 兆字节的块,分布在许多服务器上。
  • [1:07:10] 写入 GFS 的 10 太字节的爬取网页内容,即使作为一个大文件,也会自动分割成 64 千字节的块,均匀分布在所有 GFS 服务器上。
  • [1:07:35] 对于一个以整个爬取网页作为输入的 MapReduce 作业,数据已经均匀分割在所有服务器上,因此有一千台服务器时,一千个 map 工作进程各自从一千个 GFS 文件服务器并行读取千分之一的输入。

MapReduce 网络瓶颈与 GFS 数据访问

  • [1:08:21] 问题是 Google 是否在独立的物理机器集上运行 GFS 和 MapReduce。
  • [1:08:48] 关于 GFS 和 MapReduce 之间的箭头涉及什么,答案随着 Google 系统的发展多年来发生了变化。
  • [1:08:58] 在最一般的情况下,大文件存储在像 GFS 这样的网络文件系统中,这有点像 AFS。
  • [1:09:18] MapReduce 工作进程可能必须通过网络与正确的 GFS 服务器通信以获取其输入。
  • [1:09:36] 这种网络获取方法最终成为 MapReduce 实际工作的方式,但这意味着大量的网络通信。
  • [1:10:05] 在本文的 2004 世界中,他们的 MapReduce 系统中最具约束力的瓶颈是网络吞吐量。
  • [1:10:43] 所有机架以太网交换机都与一个根以太网交换机通信,因此至少有一半时间通信通过它。
  • [1:11:17] 将根交换机的总吞吐量除以大约 2,000 台服务器,每台机器只有 50 兆比特每秒。
  • [1:11:50] 与磁盘和 CPU 速度相比,50 兆比特每秒是一个巨大的限制,因此设计采用了技巧来避免使用网络。

GFS 与 MapReduce 数据本地性

  • [1:12:14] GFS 服务器和 MapReduce 工作节点运行在同一组一千台机器上。
  • [1:12:28] 当主节点拆分 map 工作时,它从 GFS 确定哪个服务器在本地磁盘上持有每个输入文件。
  • [1:12:50] 主节点将每个输入文件的 map 发送到同一台机器上的 MapReduce 软件。
  • [1:12:57] 默认情况下,读取是从本地磁盘进行的,不涉及网络。
  • [1:13:03] 根据故障或负载情况,它不能总是这样做,但几乎所有的 map 都在存储数据的机器上运行,节省了通过网络移动输入数据的时间。
  • [1:13:22] Map 输出存储在运行 map 的机器的本地磁盘上,因此存储输出不需要网络通信。

MapReduce shuffle 与网络成本

  • [1:13:54] 在某些机器上产生输出需要网络通信。
  • [1:14:06] shuffle 将键从由运行 map 的机器按行存储,转变为由负责 reduce 的机器按列存储。
  • [1:14:21] 论文将这种从行存储到列存储的转换称为 shuffle。
  • [1:14:27] shuffle 需要将每一条数据通过网络从产生它的 map 移动到需要它的 reduce。
  • [1:14:32] 这种网络移动是 MapReduce 中昂贵的部分。
  • [1:14:51] 可以想象一种更流式的 reduce,但演讲者还没有深入思考过,也不知道它是否可行。
  • [1:15:01] 他们的首要目标是让那些对系统内部一无所知的人也能轻松编程。
  • [1:15:16] reduce 函数规范的流式版本可能不会看起来这么简单。

MapReduce 的现代后继者

  • [1:15:36] 人们通过 MapReduce 的现代后继者变得更加成熟。
  • [1:15:39] 这些后继者通常处理数据流,而不是使用批处理方法。
  • [1:15:48] MapReduce 是一种批处理方法,因为它等到所有数据都可用后才进行处理。
  • [1:15:55] 批处理方法需要有限输入的概念。
  • [1:15:59] 现代系统通常使用流,并能从中利用一些效率优势。

MapReduce Shuffle 与输出网络流量

  • [1:16:12] shuffle 阶段是所有网络流量发生的地方,可能涉及大量数据。
  • [1:16:24] 对于排序,输出大小等于输入大小,因此排序 10 TB 会在网络上移动 10 TB。
  • [1:16:40] 对于许多(尽管不是所有)MapReduce 作业来说,这是大量数据,并且某些阶段可以显著减少数据。
  • [1:16:49] 人们经常希望将 reduce 的输出馈送到另一个 MapReduce 作业中。
  • [1:16:56] reduce 的输出可能非常巨大,比如排序或网页索引,例如 10 TB 输出对应 10 TB 输入。
  • [1:17:04] Reduce 输出也存储在 GFS 上,框架将键值对收集到巨大的文件中。
  • [1:17:24] 需要另一轮网络通信来将每个 reduce 的输出传送到存储它的 GFS 服务器。
  • [1:17:48] 因为 GFS 保留两到三个副本以实现容错,所以总有一个副本必须通过网络写入不同的服务器。

现代数据中心网络与 MapReduce

  • [1:18:16] 单根网络布局是许多期望的数据中心任务的限制因素。
  • [1:18:22] 现代数据中心网络在根部的速度比这种早期设计快得多。
  • [1:18:28] 典型的现代数据中心网络有许多根交换机而不是单个根交换机,每个机架交换机连接到每个复制的根交换机,流量在它们之间分配。
  • [1:18:49] 因此,现代数据中心网络具有高得多的网络吞吐量。
  • [1:18:52] 据报道,谷歌几年前停止使用 MapReduce。
  • [1:19:01] 在此之前,现代 MapReduce 不再尝试在存储数据的同一台机器上运行 map,而是乐于从任何地方加载数据,假设网络极快。

MapReduce 总结与实验

  • [1:19:16] MapReduce 的时间到了,还有一个实验。
  • [1:19:21] 下周末的实验涉及编写一个稍微简化的 MapReduce。
  • [1:19:30] 讲师说玩得开心,周四见。

[0:01] 好的,让我们开始吧。这是 6824,分布式系统。嗯,谢谢。所以我想先简要解释一下我认为什么是分布式系统。谢谢。它的核心是一组协作的计算机,它们通过网络相互通信以完成某些连贯的任务。我们在这门课上将关注的例子包括大型网站的存储,或像 MapReduce 这样的大数据计算,嗯,还有一些更奇特的东西,比如点对点文件共享。

[0:43] 这些只是我们将要研究的案例研究类型的例子。嗯,而所有这些之所以重要,是因为许多关键基础设施都是由分布式系统构建的。需要多台计算机才能完成工作的基础设施,或者本质上需要在物理上分散的基础设施。嗯。所以人们构建这些东西的原因,首先,在我甚至谈论分布式系统之前,我只想提醒你,如果你在设计一个系统,你需要解决一些问题,如果你能在单台计算机上解决它的话。

[1:17] 你知道,在不构建分布式系统的情况下,你应该那样做。而且,在单台计算机上可以完成非常非常多的工作,并且总是更容易。所以对于分布式系统,你应该在尝试构建分布式系统之前先尝试其他所有方法,因为它们并不更简单。因此,人们被驱使使用大量协作计算机的原因是:他们需要获得高性能。思考这一点的方式是,他们想要实现某种并行性。大量CPU、大量内存、大量磁盘臂并行移动。

[1:54] 人们构建这些东西的另一个原因是能够容忍故障。哇。。让两台计算机做完全相同的事情。如果其中一台发生故障,你可以切换到另一台。另一个原因是有些问题在空间上天然就是分散的。嗯,你想进行银行间的资金转账之类的。银行A在纽约市有这台计算机,银行B在伦敦有这台计算机。

[2:25] 你知道,你只需要有某种方式让它们相互通信并合作,才能完成这件事。所以有一些天然物理原因导致系统本质上就是物理分布的,而人们构建这些东西的最后一个原因是为了实现某种安全目标。所以通常,如果有某些你不信任的代码,或者你需要与某人交互,他们可能是恶意的,或者他们的代码可能有缺陷。所以你不希望不得不信任它。你可能希望拆分计算,这样你的东西在那台计算机上运行,我的东西在这台计算机上运行,它们只相互通信。

[3:03] 通过某种狭窄定义的网络协议进行通信。所以我们可能担心安全,而这通过将事物拆分到多台计算机上来实现,以便它们可以被隔离。嗯。这门课程的大部分内容将关于性能和容错,尽管另外两个也常常通过我们要研究的案例研究的约束方式体现出来。嗯,你知道,所有这些分布式系统问题都是如此,因为它们有许多部分,而且这些部分并发执行,因为有多台计算机。

[3:42] 你会遇到并发编程中出现的所有问题,所有那些复杂的交互和奇怪的依赖时序的东西。这就是分布式系统难以处理的部分原因。另一件使……分布式系统难以处理的事情是,因为你再次拥有多个部分加上一个网络。你可能会遇到非常意外的故障模式,也就是说,如果你有一台单计算机,通常情况是计算机要么工作,要么可能崩溃或遭遇断电之类。但它基本上要么工作要么不工作。

[4:12] 由许多计算机组成的分布式系统,可能会出现部分故障。也就是说,一些部分停止工作,其他部分继续工作。或者计算机在工作,但网络的某些部分损坏或不可靠。嗯,所以部分故障是分布式系统难以处理的另一个原因。所以这些是基本挑战。再见。谢谢。谢谢。

[4:44] 再见。字幕由Amara.org社区提供 谢谢。谢谢。而它难以处理的最后一个原因是,你知道,构建分布式系统的原始原因通常是为了获得更高性能。为了获得1,000台计算机的性能,或者1,000个磁盘臂的性能。但实际上,用一千台计算机获得一千倍的加速是非常棘手的。经常会有很多障碍挡在你面前。嗯,你好。

[5:15] 谢谢。谢谢。通常需要一些仔细的设计才能……让系统真正给你你认为应得的性能。所以解决这些问题,当然,可能完全在于处理这些问题。嗯,学习这门课程的原因是,这些问题和解决方案通常技术上相当有趣,而且它们是难题。对于其中一些问题,已知有相当好的解决方案;对于其他问题,则没有这么好的解决方案,没有。

[5:46] 分布式系统被现实世界中的许多系统使用,大型网站经常涉及。你知道,大量计算机被组合成分布式系统。当我第一次教这门课程时,分布式系统还是一种学术上的好奇。你知道,人们认为,“哦,你知道,在小规模上,它们有时被使用,人们觉得,哦,总有一天它们会……可能很重要。”但现在,尤其是受巨型网站崛起的推动。

[6:17] 这些网站拥有你知道的大量数据和装满计算机的整个仓库,分布式系统在过去20年里已经成为计算基础设施中非常—— seriously重要的部分。好的。这意味着人们已经对它们投入了很多关注,很多问题已经解决,但仍有很多未解决的问题。所以如果你是研究生或者对研究感兴趣,分布式系统中还有很多问题有待解决。你可以研究他的研究。

[6:49] 最后,如果你喜欢构建东西,这是一门好课,因为它有一个实验序列,你将在其中构建一些相当现实的分布式系统,重点关注性能和容错。所以你会有很多练习。构建分布式系统并让它们工作。好的。在我开始真正的技术内容之前,让我先谈谈课程结构。你应该能够找到课程网站。

[7:20] 使用 Google。课程网站上还有实验作业、课程安排,以及一个 Piazza 的链接,你可以在那里发布问题、获得解答。嗯,课程工作人员,我是 Robert Morris,将负责授课。我还有四位助教。你们想站起来露个面吗?嗯,谢谢。助教们是专家,尤其擅长解决实验,他们会安排答疑时间,所以如果你对实验有疑问,应该去答疑时间。

[7:54] 或者你可以把问题发到 Piazza。嗯,谢谢。这门课有几个重要组成部分。嗯,一个是讲座。几乎每节课都有一篇论文。谢谢。谢谢。有两次考试。谢谢。谢谢。谢谢。再见。还有实验,编程实验,嗯,还有一个可选的期末项目,你可以用它代替其中一个实验。

[8:27] 谢谢。字幕由 Amara.org 社区提供。讲座将围绕分布式系统中的重要思想展开。也会有几节课更多是关于实验编程方面的内容。很多讲座会被案例研究占据,我试图引出分布式系统内容的方式,很大程度上是通过看论文——有些是学术论文,有些是业界人士写的,描述真实问题的真实解决方案。

[9:04] 嗯,这些讲座实际上会被录像。我希望把它们放到网上,这样如果你不在现场,或者想复习讲座,就能看录像讲座。阿门。论文方面,同样是每周读一篇。大多数是研究论文。有些是经典论文。比如今天的论文,我希望有些人已经读过,是关于 MapReduce 的。这是一篇老论文,但它是开端,激发了大量有趣的工作,既有学术界的,也有现实世界中的。所以有些是经典论文,有些是较新的论文。

[9:38] 谈论更前沿的研究,人们当前担心的问题。从这些论文中,我希望梳理出基本问题是什么,人们有过哪些想法,这些想法在解决分布式系统问题时可能有用也可能没用。嗯,我们有时会看其中一些论文的实现细节。因为很多内容都与基于软件的系统的实际构建有关。我们还会花一定时间看评估。人们通过测量来评估他们的系统有多容错,或者人们测量性能有多高,或者他们到底有没有获得性能提升。

[10:14] 嗯,所以我希望你们都在来上课前读过论文。讲座……如果你还没读过论文,可能就不太听得懂,因为没有足够时间既解释论文的全部内容,又对论文的意义做有趣的反思。在线课程你真的必须在来上课前读论文,希望你们在这门课上学到的一件事就是如何快速高效地读论文,跳过那些可能不太重要的部分,专注于梳理出重要想法。

[10:50] 在网站上,课程安排中的每个链接都对应一个问题。每篇论文你都要提交一个答案。我想答案的截止时间是午夜。我们还要求你提交一个关于该论文的问题。嗯,提交到网站上,既是为了在我准备讲座时给我一些思考素材,也是因为如果我有时间,我会尽量通过电子邮件至少回答其中几个问题。每篇论文的问题和答案截止时间是午夜,也就是前一天晚上。

[11:21] 有两次考试,一次是课堂上的期中考试,我想是在春假前的最后一节课。嗯,还有一次期末考试,在学期末的期末考试周。考试主要侧重于论文和实验。准备考试的最佳方式,除了上课和读论文之外,嗯,一个很好的准备方式是看往年试卷。

[11:52] 20 年的往年试卷和答案。所以你看看这些,感受一下我喜欢问什么样的问题。事实上,因为我们读的很多是同样的论文,不可避免地,我每年问的问题都难免与往年问过的问题相似。谢谢。实验方面,有四个编程实验。第一个实验下周星期五截止。嗯,它们……

[12:23] 谢谢。实验一是……谢谢。一个简单的 MapReduce 实验。实现你自己版本的论文。我几分钟后会讨论那篇论文。嗯,实验二。涉及使用一种叫做 raft 的技术来实现容错,为了,嗯,理论上允许任何系统通过复制它并让这种 raft 技术管理复制、管理自动切换(如果某个复制服务器发生故障)来实现容错。

[12:59] 所以这就是用于容错的 RAFT。嗯。谢谢。字幕由 Amara.org 社区提供 *亲吻* 在实验三中,你将使用你的 raft 实现来构建一个容错的键值服务器。谢谢。阿门。谢谢。它将被复制并且容错。在实验四中,你将拿你的复制键值服务器,把它克隆成若干个独立组。并且你将把键值存储系统中的数据拆分到所有这些单独的复制组上,以获得并行加速。

[13:37] 通过并行运行多个复制组,你还将负责在不同服务器来来去去时在它们之间移动各个数据块。不掉任何一个球。这通常被称为分片的,再见。键值服务。再见。你 分片指的是拆分数据,对数据进行分区。在多台服务器之间以获得并行加速。

[14:10] 嗯 谢谢。如果你愿意,你可以不做实验四,而是做一个你自己选择的项目。这里的想法是,如果你对分布式系统有一些想法,你知道,按照……我们在课上讨论的一些分布式系统的风格,如果你有自己的想法想要追求,并且你喜欢构建一些东西并衡量它是否有效 探索你的想法。你可以做一个项目。嗯,所以对于项目,你会挑选一些队友,因为我们要求项目以两到三人的团队完成。

[14:45] Nam。所以像一些队友一样,把你的项目想法发给我们,我们会考虑一下并说行或不行,也许给你一些建议。嗯,然后如果你继续做,如果我们说行,并且你想做一个项目,你就做那个而不是实验 4,而且它是在学期末做的。你知道,你会……你应该做一些设计工作并构建一个真实的系统,然后在课程的最后一天,你将演示你的系统。以及交给我们一份简短的……关于你构建了什么的书面报告。我在网站上发布了一些想法,这些想法可能对你有用,也可能没用,可以激发你关于可以构建什么项目的想法,但真正最好的项目是你对项目有好的想法的项目。这个想法是,如果你想做一个项目,你应该选择一个与本课程中我们要讨论的系统类似的想法。

[15:40] 好,回到实验。我们给你的实验成绩,你提交你的实验代码,我们对它运行一些测试,你的成绩基于你通过了多少测试。我们把你我们使用的所有测试都给你,所以没有隐藏测试。所以,如果你影响实验并且它可靠地通过所有测试,那么很有可能,除非有一些奇怪的事情发生,而有时确实会发生。很有可能如果你的代码在你运行时通过了所有测试,那么在我们运行时它也会通过所有测试。并且你会得到满分。所以希望你能得到什么分数不会有谜团。

[16:13] 关于实验。嗯,让我提醒你,调试这些实验可能很耗时。因为它们是分布式系统,并且有大量的并发和通信,嗯,那种奇怪的、难以调试的错误可能会出现。你真的应该尽早开始实验。不要把它们留到……如果你把实验留到最后一刻,会有很多麻烦。你必须尽早开始。如果你有——问题,请来助教的答疑时间。

[16:44] 并且请随时提问。在 Piazza 上关于实验的问题。事实上,我希望如果你知道答案,你也会在 Piazza 上回答别人的问题。好的。关于课程机制有什么问题吗?是的?再见。是的。谢谢。所以问题是,这些事情如何计入成绩?我忘了,但都在……

[17:18] 它在网站上的——某个地方。嗯。我认为实验是最重要的单一组成部分。谢谢。好的。谢谢。嗯……好的,所以这是一门关于应用程序基础设施的课程。所以贯穿这门课程,我谈论事物的方式会有一种区分,即在应用程序之间,应用程序是其他人,客户,别人写的。

[17:49] 应用程序将使用我们在这门课程中思考的基础设施。所以经常出现的那类基础设施。谢谢。谢谢。是存储 谢谢。通信 谢谢。和计算。我们将讨论提供所有这三种基础设施的系统。

[18:19] 嗯,存储 事实证明,存储将是我们最关注的一个,因为它是一个非常明确且有用的抽象。谢谢。通常相当直接的抽象。所以人们很了解如何使用和构建存储系统,以及如何构建那种复制的、容错的、高性能的分布式存储实现。我们还会讨论一些我们的计算系统,比如今天的 MapReduce。

[18:50] 是一个计算系统。嗯,我们也会谈一些通信,但主要是从我们构建分布式系统所需工具的角度。比如计算机必须通过网络相互通信,你知道,也许你需要可靠性之类的。所以我们会谈一点,但实际上我们主要是……通信的消费者。嗯,如果你想了解通信系统或者它们如何工作,那更多是 6829 的主题。所以对于存储和计算,我们的很多目标是能够发现抽象,嗯,简化这些存储和计算分布式存储和计算基础设施接口的方法,以便在其上构建应用程序变得容易。

[19:41] 而这真正意味着我们需要,我们希望能够在这些系统的分布式性质之上构建抽象,隐藏这些系统的分布式性质。所以梦想,这个梦想很少完全实现,但梦想是能够构建一个接口,对应用程序来说看起来像是一个非分布式存储系统,就像文件系统或每个人都已经知道如何编程并且有相当简单模型语义的东西。我们很想能够构建看起来和表现得就像非分布式存储和计算系统一样的接口,但实际上——你知道,在底层是庞大的、极其高性能的、容错的分布式系统。

[20:23] 嗯。所以我们很希望能有抽象。谢谢。字幕由 Amara.org 社区提供。谢谢。而且随着课程的推进,你们会看到,我们大概只走了一部分路。很少能找到一种针对分布式存储或计算的抽象,它具有简单的行为,表现得就像大家都理解的、非分布式版本的存储一样。人们在这方面越来越擅长,而且……

[20:54] 嗯,我们将尝试研究人们已经学到的关于构建此类抽象的方法。好的。当我们考虑这些抽象时,会出现哪些类型、哪些主题呢?第一个,我们将经常看到的第一个主题,一般主题,在我们研究的许多系统中,都与实现有关。谢谢。嗯,例如,人们学习如何构建这些系统时经常看到的工具,比如远程过程调用,其目标是掩盖我们通过不可靠网络进行通信这一事实。

[21:38] 嗯,另一种实现主题我们将经常看到的是线程。这是一种编程技术,使我们能够利用多核计算机,但也许对本课程更重要的是,线程是一种组织并发操作的方式,希望它能简化程序员对这些并发操作的看法。嗯,而且因为我们会大量使用线程,事实证明,从实现层面来说,我们还需要花一定时间思考并发控制,比如锁之类的东西。

[22:18] 嗯。你 谢谢。这些实现思想在课程中主要出现的地方,会在许多论文中涉及,但你们将在实验室中大规模地直面所有这些内容。你需要构建分布式系统。你知道,为分布式系统做编程。这些就像许多重要的工具,超越了普通的编程,嗯,这些是你需要使用的关键工具之一。我回来了。来构建分布式系统。

[22:50] 我们将要讨论的所有论文中出现的另一个大主题是性能。谢谢。再见。谢谢。谢谢。嗯,通常构建分布式系统的高层目标是获得人们所说的可扩展加速。所以我们将关注可扩展性。我所说的可扩展性或可扩展加速是指,如果我用一台计算机解决某个问题,然后我买第二台计算机来帮助我执行我的问题。

[23:30] 如果我现在能用一半的时间解决这个问题,或者也许在两台计算机上每分钟解决两倍的问题实例,就像在一台计算机上一样,那么这就是可扩展性的一个例子。差不多。两倍的计算机或资源,嗯,能给我两倍的性能或吞吐量。这是一个巨大的锤子。如果你能构建一个实际上具有这种行为的系统,即如果你把投入问题的计算机数量增加某个因子,你就能得到那个因子的更多吞吐量、更多性能。

[24:14] 从系统中出来。这是一个巨大的胜利。因为你可以用钱买计算机。对吧?而如果为了获得替代方案,嗯,为了获得更多性能,你必须付钱给程序员来重构你的软件以获得更好的性能,使其更高效,应用某种专门技术、更好的算法之类的。如果你必须付钱给程序员来修复你的代码使其更快。

[24:44] 这是一种昂贵的方式。我们希望能直接,哦,买一千台计算机而不是 10 台计算机,然后获得你知道的 100 倍的吞吐量。那太棒了。所以这种可扩展性的想法在人们构建大型网站之类的东西时,是一个巨大的想法,你知道,一栋装满计算机的大楼。如果那栋装满计算机的大楼是为了获得相应数量的数据性能,你必须小心设计才能真正获得那种性能。嗯,所以,当我们在本课程中看图表或画图表时,这通常看起来像是,假设我们正在构建一个网站。

[25:26] 通常,你可能有一个网站,你知道,有一个 HTTP 服务器,或者假设它有一些用户。嗯,运行着网络浏览器,然后他们与……你知道,运行 Python 或 PHP 之类的 Web 服务器通信,某种 Web 服务器。然后 Web 服务器与某种数据库通信。嗯,你知道,当你有一两个用户时,可以让一台计算机同时运行两者,或者也许一台计算机用于 Web 服务器,一台计算机用于数据库,也许突然你变得非常受欢迎,你知道,100 百万人注册了你的服务。

[26:10] 对吧?你怎么……不。你怎么修复你的——你当然不能——在单台计算机上支持数百万人,嗯,除非通过极其仔细的劳动密集型优化。嗯,但你没时间这么做。所以,通常你加速的方式是,你做的第一件事就是买更多 Web 服务器,然后拆分用户,这样你知道,一半用户或某个比例的用户去 Web 服务器一,另一半你把他们送到 Web 服务器二。

[26:40] 而且因为也许你在构建,我不知道,Reddit 之类的,所有用户最终都需要看到相同的数据,你让所有 Web 服务器与后端通信。也许你可以在这里继续添加 Web 服务器很长时间。谢谢。嗯,谢谢。所以这是一种在 Web 服务器代码上获得并行加速的方式。你知道,如果你运行 PHP 或 Python,也许它效率不太高。嗯,呃,只要每个单独的 Web 服务器不会给数据库带来太多负载,你就可以添加很多 Web 服务器。

[27:13] 在遇到问题之前。但是。不幸的是,这种可扩展性很少是无限的。嗯,当然不是不经过认真思考就能做到的。所以这些系统通常会发生的情况是,在你拥有 10 或 20 或 100 台 Web 服务器都与同一个数据库通信之后的某个时刻,突然间数据库开始成为瓶颈。再增加更多 Web 服务器也不再有帮助。所以,通过不断增加无限数量的计算机来获得完全的可扩展性是很罕见的。

[27:45] 在某个时刻你会耗尽动力,因为你增加更多计算机的地方不再是瓶颈。通过拥有大量 Web 服务器,我们基本上把瓶颈转移了。嗯,我认为是从 Web 服务器到数据库的性能限制。嗯,而到了这个时候,实际上,你几乎肯定必须做一些设计工作。因为很少能有一种直接的方法,把单个数据库拿来,对它进行某种重构。你可以把存储在单个数据库中的数据重构,使其拆分到多个数据库上。

[28:21] 嗯,但这通常是相当多的工作。而且因为这很麻烦,但很多人实际上需要这样做。嗯,在这门课程中我们会看到很多例子,其中人们谈论的分布式系统是一个存储系统。因为作者们当时在运行,你知道,类似一个大型网站,它在单个数据库或存储服务器上耗尽了动力。嗯,总之,可扩展性的故事是:我们喜欢构建以这种方式扩展的系统,但是,嗯,你知道,很难做到,或者通常需要工作、设计工作,才能把这个想法无限推进下去。

[29:04] 阿门。谢谢。谢谢。好的,那么。另一个经常出现的重大主题是容错。谢谢。如果你构建的系统里只有一台计算机,那么,一台计算机通常可以连续运行多年。比如,我办公室里有服务器已经连续运行多年而没有崩溃。嗯,你知道,计算机相当可靠,操作系统相当可靠,显然我所在大楼的电力也相当可靠。所以,单台计算机能连续运行惊人的长时间并不罕见。

[29:44] 然而,如果你用数千台计算机构建系统,那么即使每台计算机预计能连续运行一年,一千台计算机就意味着你每天大约会有三次计算机故障。在你的计算机集合中。用大型分布式系统解决大问题,把那种非常罕见的容错、非常罕见的故障问题,变成了时时刻刻都在发生的故障问题。在一个有一千台计算机的系统中,几乎总是有某个东西是坏的。总有一些计算机要么崩溃了,要么神秘地运行不正确,要么运行缓慢,要么做错事。

[30:25] 或者也许网络的某个部分,比如有一千台计算机,我们有很多网线。还有很多网络交换机。你知道,总有一些网线被人踩到而不可靠,或者网线掉了,或者某个网络交换机的风扇坏了,交换机过热而失效。在你那栋楼大小的分布式系统中,总会有某个小问题。所以大规模把问题从非常罕见的事件——你其实不必太担心——变成了持续不断的问题。

[30:57] 故障必须真正地,或者说对故障的响应、对故障的掩盖、感知故障的能力,必须内建到设计中。因为故障总是存在。嗯……而且,你知道,作为为应用程序员构建便利抽象的一部分,我们确实需要能够构建基础设施,尽可能地对应用程序员隐藏故障或掩盖故障之类的。这样每个应用程序员就不必为可能发生的所有不同种类的故障都准备一套完整而复杂的方案。

[31:32] 嗯,关于容错意味着什么,你可以有各种不同的概念。稍后再多讲一点。但我们在那个词上到底指什么。我们会看到很多不同的形式,但在你看到的更常见的想法中,一个是可用性。谢谢。阿门。所以,你知道,有些系统被设计成在某些种类的故障下——不是所有故障,而是某些种类的故障——系统会在故障存在的情况下继续运行,同时提供未受损的服务。

[32:15] 呃,提供与没有发生故障时本会提供的相同种类的服务。所以有些系统在那个意义上是可用的。所以如果你构建一个复制的服务,也许有两份副本,你知道,如果其中一个副本服务器失败了,也许另一台服务器可以继续运行。当然,如果两者都失败,你就不能。你知道,你不能保证。嗯。那种情况下的可用性。所以可用的系统通常会说,好吧,在一组特定的故障下,我们会继续提供服务。我们会保持可用。

[32:48] 如果发生的故障比那更多。它就不再可用了。谢谢。你可能拥有或除了可用性之外或单独拥有的另一种容错是恢复性。谢谢。谢谢。谢谢。这意味着如果出了什么问题,也许服务会停止工作。也就是它干脆停止响应请求,嗯,然后它会等待有人来修复出问题的地方,但在修复发生之后,系统将能够继续运行,就像没有出过任何坏事一样。

[33:23] 所以这比可用性的要求要弱一些,因为在这里,在故障组件被修复之前,我们不会做任何事情,但事实上我们能够重新启动并继续运行,而不会损失任何正确性,这仍然是一个重要的要求。这意味着,可恢复系统通常需要做诸如将最新数据保存到磁盘之类的事情,以便在电源恢复后能够取回数据。嗯,而且即使在可用系统中,为了使系统在现实生活中实用,通常可用系统的规格是:它们会一直可用,直到发生一定数量的故障。如果发生了太多故障,可用系统将停止工作或完全停止响应,但当足够多的东西被修复后,它将继续运行。所以一个好的可用系统在某种意义上也应该是可恢复的,即如果发生太多故障,

[34:26] 嗯,它会停止应答,但之后会继续正确运行。嗯,所以这就是我们喜欢听到的。这就是我们希望获得的。最大的工具,我们将看到多种解决这些问题的方法。我说过,这个领域最重要的两个工具。一个是非易失性存储。这样,如果某东西崩溃了、电源故障了,或者别的什么,也许是整栋楼停电。我们可以使用非易失性存储,如硬盘、闪存或固态硬盘等,来存储检查点或日志,记录系统的状态,然后当电源恢复或有人修好我们的电源时,谁知道呢,我们就能从硬盘读取最新状态并继续运行。

[35:22] 所以。所以一个工具是非易失性存储。而非易失性存储的管理经常出现,因为非易失性存储的更新往往很昂贵。因此,构建高性能容错系统的大量细节工作在于用巧妙的方法避免过多地写入非易失性存储。在过去甚至今天,写入非易失性存储意味着移动磁盘臂并等待磁盘盘片旋转。

[35:58] 这两者都慢得令人痛苦,相对于3千兆赫兹微处理器的尺度。有了闪存之类的东西,情况好多了,但仍然需要大量思考才能获得良好性能。我们用于容错的另一个重要工具是复制。谢谢。而复制副本的管理有点棘手。你知道,任何复制系统中都潜伏着这样的问题:我们有两台服务器,每台都有一份据称相同的系统状态副本。

[36:32] 嗯,出现的关键问题总是两个副本会意外失去同步,不再成为副本。而这正是——你知道,在我们将要看到的每一个使用复制来实现容错的设计背后。还有实验2,这就是你们要做的全部内容。为容错管理复制副本。嗯,正如你将看到的,这相当复杂。嗯,最后一个主题,最后一个跨领域主题,嗯,是一致性。

[37:11] 谢谢。谢谢。那么作为我所说的一致性含义的一个例子,假设我们正在构建一个分布式存储系统,它是一个键值服务,所以它只支持两个操作,也许有一个put操作,你给它一个键和一个值,存储系统就把这个值作为这个键的值存起来,所以它只是维护一个大表,包含键和值。然后有一个get操作。客户端发送一个键,存储服务应该响应存储在该键下的值。

[37:51] 这有点像——当我除了分布式系统想不出别的例子时,我就会拿出键值服务。它们非常有用,对吧?它们只是存储系统的基本的、简单的版本。所以。当然,如果你是一个应用程序员。如果……这两个操作有附带的含义,那会很有帮助。你可以去查手册,手册会说明,你知道,它是什么意思,如果你调用get会得到什么。

[38:23] 对,以及你调用put意味着什么。所以如果能有某种规范来说明它们的含义,那就太好了,否则,你怎么可能在没有描述put和get应该做什么的情况下编写应用程序呢。嗯,这就是一致性的主题。它在分布式系统中之所以有趣,是因为嗯。无论是为了性能还是为了容错原因,容错原因,我们经常有不止一份数据在周围浮动。所以,你知道,在一个非分布式系统中,你只有一个服务器和一个表,通常,尽管并非总是如此。

[39:02] 通常相对而言,put和get在直觉上可能意味着什么并没有歧义。你知道,put的意思是更新表,而get的意思就是,给我表中存储的版本,嗯,但在一个分布式系统中,由于复制或缓存或谁知道什么原因,数据有不止一份副本。这个键值对可能有多个不同的版本在周围浮动。比如,如果其中一个副本,你知道,假设某个客户端发出一个put,而且你知道,有两份服务器副本,所以它们都有一个键值表。

[39:46] 对,也许键一在两个副本上的值都是 20。谢谢。然后某个客户端发起一个 put 请求。我们这里有一个客户端。它要发送一个 put,想把键一的值更新为 21。也许它是在这个键值服务器里计数,所以它发送一个 put。谢谢。带着键一和值 21,它把它发给第一台服务器,然后它即将发送同样的,你知道,它想更新两个副本,对吧?

[40:19] 它让它们保持同步。它正要发送这个 put,但就在它把 put 发给第二台服务器之前,它崩溃了。断电、操作系统里的 bug 之类的。所以现在不幸的是,我们留下的状态是,我们发送了这个 put,于是我们把两个副本中的一个更新成了值 21,但另一个仍然是 20。现在有人来了,用“get”来读取。他们可能会得到……他们想……读取与键一关联的值,他们可能会得到 21,也可能会得到 20,取决于他们跟谁通信。而且即使规则是你总是先跟上面那台服务器通信,如果你在构建一个容错系统,实际的规则必须是:哦,你先跟上面那台服务器通信,除非它已经失效,在这种情况下你就跟下面那台服务器通信。

[41:00] 嗯,所以无论哪种方式,总有一天你会冒着把这个过时的数据副本暴露给未来某个 get 的风险。可能有很多 get 都拿到了更新后的 21,然后就像下周,突然间,某个 get 返回了,你知道,一周前的数据副本。所以那不是很一致。对吧?按顺序,但你知道,这是那种可能发生的事情。对吧?如果我们不小心的话。鉴于这种由于复制而带来的危险,我们实际上需要写下关于 put 和 get 的规则将会是什么。

[41:37] 而事实证明,一致性可以有很多不同的定义。嗯,其中许多相对直接。许多听起来像是,嗯,我的 get 返回由最近完成的 put 所写入的值。好吧。所以这通常被称为强一致性。事实证明,构建具有弱得多的一致性的系统也非常有用。例如,它们不保证任何类似“我的 get”这样的东西。

[42:11] 看到最近一次 put 写入的值。而原因是,所以有强一致的系统——它们通常有某种形式的 get 能看到最近的 put。我想你得……有很多细节要弄清楚。也有弱一致性,很多种弱一致系统,它们不做任何这样的保证。关于那一点。它可能向你保证,嗯,你知道,如果有人做了一个 put,那么你可能看不到这个 put。你可能会看到没有被这个 put 更新的旧值,时间可能是不确定的。

[42:47] 嗯,而人们之所以对弱一致性方案非常感兴趣,是因为强一致性,也就是说,让读操作实际上看到、被保证看到最新的,对吧。那是一个非常昂贵的规范来实现。嗯,因为这意味着几乎可以肯定你必须,必须有人做大量的通信才能实际实现某种强一致性的概念。如果你有多个副本,嗯,这意味着要么写者要么读者,或者也许两者,都必须咨询每一个副本。就像在这个例子中,嗯,也许一个客户端崩溃了,留下一个更新了,但另一个没有。

[43:29] 如果我们想在这个系统里以一种也许简单的方式实现强一致性,我们会让读者读取两个副本,或者如果有不止一个副本,就读取所有副本。并使用他们找到的最近写入的值。嗯。但那很昂贵。读取一个值要有很多闲聊。所以为了尽可能避免通信,嗯,特别是如果副本相距很远,人们会构建弱系统,这种系统实际上可能允许在这种情况下读取到旧值的过时读。

[44:01] 嗯,尽管通常会有更多语义附加到那上面,试图让这些弱方案……而通信问题,你知道,强一致性需要昂贵的通信。这真正让你陷入麻烦的地方是,如果我们使用复制来实现容错,那么我们真的希望副本具有独立的故障概率,具有不相关的故障。所以,例如,把我们数据的两个副本放在同一个机架、同一个机房里,可能是个非常糟糕的主意。

[44:38] 因为如果有人绊到了那个机架的电源线,我们数据的两个副本都会死掉。因为它们都连在同一个机架的同一根电源线上。嗯,所以为了尽可能让副本在故障上独立,以获得像样的容错性,人们会很乐意把不同的副本放得尽可能远,比如放在不同的城市,或者也许在大陆的两边。这样,摧毁一个数据中心的地震极不可能也摧毁拥有另一个副本的另一个数据中心。

[45:13] 嗯,你知道,所以我们很希望能做到那样。如果你那样做,那么另一个副本就在数千英里之外,而光速意味着跨大陆通信到一个数据中心以更新数据的另一个副本可能需要毫秒或几十毫秒量级的时间。所以这使得强一致性、良好一致性所需的通信可能极其昂贵。就像每次你想做这些 put 操作之一,或者也许一个 get,取决于你如何实现,你可能得坐在那里等大约 10 或 20 或 30 毫秒,才能与两个数据副本通信,以确保它们都被更新或都被检查。

[45:57] 来查找最新副本。嗯,而且那笔巨大的开销,对吧?在毕竟每秒会执行约十亿条指令的机器上,这是 10 或 20 或 30 毫秒。所以我们在等待时浪费了大量潜在的指令。人们常常构建弱得多的系统。你只被允许更新最近的副本,或者只查询最近的副本。现在,我的意思是,关于弱一致性保证,有大量学术和现实世界的研究,使它们实际上对应用有用,以及如何利用它们来真正获得高性能。

[46:35] 谢谢。好的,那是对课程中……技术思想的闪电式预览。在开始讲 MapReduce 之前,对此有什么问题吗?好的,我想切换到 MapReduce。那是一个详细的案例研究,实际上将说明我们在这里一直在谈论的大部分思想。并且它产生了一个系统,这个系统是 呃……

[47:06] 最初由 Google 设计、构建并使用,我想那篇论文可以追溯到 2004。他们面临的问题是要在数 TB 和数 TB 的数据上运行巨大的计算。为所有网络内容创建索引,或者分析整个网络的链接结构,以识别最重要的页面或最权威的页面。

[47:36] 所以,你知道,整个网络即使在那些日子里也有数十 TB 的数据。嗯…… 为网络建立索引基本上等同于对整个数据进行某种排序。排序,你知道,就像…… 相当昂贵。而在单台计算机上对整个网络内容进行排序,我不知道要花多长时间,但你知道,数周、数月或数年之类的。所以,当时的 Google 迫切希望在数千台计算机上对海量数据运行巨大的计算。

[48:09] 以便计算能够快速完成。对他们来说,购买大量计算机是值得的,这样他们的工程师就不必花大量时间看报纸或什么的,等待他们的大型计算任务完成。嗯…… 所以有一段时间,他们让聪明的工程师手写,你知道,如果你需要编写网络索引器或某种链接、网络链接分析工具。你知道,Google 买了计算机,他们说:“给,工程师们,你们知道,在这些计算机上运行你们喜欢的任何软件。”

[48:40] 他们会费力地编写那种一次性的、手工编写的软件,把他们正在处理的任何问题,以某种方式分配到许多计算机上,组织那个计算,并把数据取回来。嗯,如果你只雇佣擅长分布式系统的工程师,也许那还行,尽管即使那样,也可能非常浪费工程精力。但他们想雇佣擅长其他东西的人。嗯,而不一定……

[49:13] 嗯…… 那些想把所有时间都花在编写分布式系统软件上的工程师。所以他们真的需要某种框架,使得他们的工程师很容易就能,对吧,处理他们想做的任何分析的核心部分,比如排序算法或网络索引或链接分析器之类的。只编写那个应用的核心部分,而不必运行,能够运行在数千台计算机上。嗯,而不必担心如何把工作分散到数千台计算机上的细节,如何组织所需的任何数据移动,如何应对不可避免的故障。

[49:49] 所以他们在寻找一个框架,使非专家能够轻松编写和运行巨大的分布式计算。嗯,这就是 MapReduce 的全部意义。阿门。其思想是,程序员只需编写应用程序设计者、这个分布式计算的使用者,只需能够编写一个简单的 map 函数和一个简单的 reduce 函数,好。对分布一无所知。而 MapReduce 框架会处理其他一切。

[50:23] 嗯,所以 MapReduce 所做事情的抽象视图是:它首先假设有一些输入,输入以某种方式被分割成一大堆不同的文件或块。我们想象,你知道,我们有输入文件一、输入文件二、输入文件三,等等。你知道,这些输入也许是 帮助。

[50:53] 从网络爬取的网页,或者更可能是包含许多网络文件的大文件——每个文件包含许多从网络爬取的网络文件。好的,MapReduce 开始的方式是,你定义一个 map 函数,MapReduce 框架将在每个输入文件上运行你的 map 函数。你 谢谢。当然你可以看到这里有一些明显的并行性可用。

[51:25] 可以并行运行这些 map。所以每个 map 函数只查看它的输入并产生输出。map 函数需要产生的输出是一个列表。它接收一个文件作为输入,文件是输入数据的某个部分,并产生一个键值对列表作为输出。map 函数。所以,例如,假设我们正在编写最简单的 MapReduce 示例,一个单词计数 MapReduce 作业,其目标是统计每个单词出现的次数。

[51:59] 所以你的 map 函数可能会发出键值对,其中键是单词,值就是一。所以对于它看到的每个单词,这个 map 函数会将输入拆分成单词。对于它看到的每个单词,它将该单词作为键发出,并将一作为值。然后稍后我们会统计所有这些一。以获得最终输出。输入一包含单词 A。以及单词 B。因此 map 将产生的输出是键 A 值 1,键 B 值 1。

[52:32] 也许第二个 map 指示看到一个文件,里面只有一个 a b,没有别的,所以它会实现输出 B1。也许第三个输入里有一个 A,还有一个 C。好,所以我们在所有输入文件上运行所有这些 map。然后我们得到这个中间结果,论文称之为中间输出。也就是对于每个 map,输出一组键值对。然后计算的第二阶段是运行 reduce。

[53:04] 谢谢。嗯,其思路是 MapReduce 框架会把每个关键字来自所有 map 的所有实例收集到一起。所以 MapReduce 框架会把所有的 A 收集到一起,你知道,从每个 map 中,每一个键为 A 的键值对,它都会把它们收集起来,交给程序员定义的 reduce 函数的一次调用。然后它会把所有的 B 收集到一起。当然,这需要真正的收集,因为不同的 B 键实例是由不同计算机上不同的 map 指示产生的。所以我们说的不是数据移动。

[53:50] 所以我们会收集所有的 B 键,并把它们交给对 reduce 的另一次调用,这次调用以所有 B 键作为参数,C 也一样,所有的 C。所以这就是 MapReduce 框架会安排的事情:对于在任何一个 map 输出中出现过的每个键,都调用一次 reduce。嗯,对于我们这个有点傻的词频统计例子,所有这些 reduce 要做的,或者说其中任何一个要做的,就是数一数传给它的项数。它甚至不需要看这些项,因为它知道每一项——这个词对应的值都是加一。你不必看那些一,我们只要数一数就行。所以这个 reduce 会产生,嗯,A,然后是计数。

[54:43] 根据它的输入,这个 reduce。它会产出与之关联的键,然后是其值的计数,这个计数也是二,谢谢。谢谢。谢谢。所以这就是一个典型的……MapReduce 作业在高层面上看起来的样子。为了完整起见,——抱歉。嗯,说一点术语。整个计算称为作业(job)。任何一次 map 或 reduce 的调用称为任务(task)。所以我们有一个完整的作业,它由一堆 map 任务组成。

[55:21] 然后是一堆 reduce 任务。嗯……那么对于这个词频统计,举个例子,map 和 reduce 函数会是什么样子。谢谢。谢谢。嗯……谢谢。谢谢。map 函数接受一个键和一个值作为参数。而现在我们说的是用普通编程语言写的函数,比如 C++ 或 Java 或者谁知道什么语言。

[55:52] 嗯,所以这只是普通人能写的代码。词频统计的 map 函数会做的是拆分——键是文件名,通常会被忽略,我们并不真的关心文件名是什么。而 V 是“这个 map 输入文件”的内容。所以 V 就包含所有这些文本。我们要把 V 拆分成单词。谢谢。谢谢。然后对于每个单词,谢谢。

[56:24] *敲击* *敲击* *敲击* 我们就发出(emit)。emit 接受两个参数。只有 map 能进行的 emit 调用,emit 由 MapReduce 框架提供。我们可以产出,我们交给 emit 一个键,也就是这个单词……和一个值,也就是字符串一。所以 map 函数就是这样。MapReduce 中的词频统计 map 函数真的可以就这么简单。

[56:56] 嗯,所以。他们那种承诺要让这个——而且,你知道,这个 map 函数对分布式或多台计算机、对需要跨网络移动数据这件事、或者谁知道什么,一无所知。这非常……直截了当。而词频统计的 reduce 函数,嗯。reduce 被调用时——记住每个 reduce 被调用时都带着某个给定键的所有实例;MapReduce 框架调用 reduce 时,会传入它负责的键以及一个包含所有 map 产生的值的向量。

[57:35] 与该键关联。键是单词,值全是一,我们并不真的关心它们,我们只关心有多少个。嗯。所以,reduce 有自己的 emit 函数,它只接受一个要作为最终输出发出的值,作为这个键的值。所以我们要发出这个数组的长度。谢谢。谢谢。所以这也差不多是 MapReduce 中 reduce 函数最简单的样子了,也就是说,极其简单。

[58:08] 而且不需要了解容错或任何其他东西?好,关于……基本框架有什么问题吗,请讲。而且不……不是必须的,但这可能会返回一些东西。我在想。比如 France、France、France。使用 MapReduce 框架,也许它用访问来 reduce。那一步做若干次。你是说你能把 reduce 的输出喂给——是的。

[58:43] 谢谢。哦,是的。哦是的,在现实中,好。在现实中,对 MapReduce 用户来说,常规做法是,你知道,定义一个 MapReduce 作业,接受一些输入并产生一些输出,然后再来第二个 MapReduce 作业,你知道,如果你在做一些非常复杂的多阶段分析或迭代算法,比如 PageRank,例如,那是 Google 用来估计不同网页有多重要或有影响力的算法。那是一个迭代算法,会逐渐收敛到一个答案。如果你用 MapReduce 实现它,我想他们最初就是这么做的,你就必须多次运行这个 MapReduce 作业。

[59:28] 每一个的输出都是——你知道,网页列表,每个网页带有一个更新后的值或权重或重要性。所以常规做法是把这个输出拿去作为另一个 MapReduce 作业的输入。我们不能永远这样做。哦是的。是这样的。所有的眼泪“嗯,是的,你需要把东西设置好,输出,你需要——reduce 函数在知识上有点……”

[1:00:00] 认识一下这些产物。数据,其格式或所含信息满足下一个 MapReduce 作业所需。我的意思是,这实际上引出了 MapReduce 框架的一个小缺点,那就是,它很棒。如果你——谢谢。如果你需要运行的算法可以很容易地表达为一个 map,随后是这种“按键对数据做洗牌,然后是一个 reduce,就这些”。对于能够以这种形式表达的算法,MapReduce 非常出色。

[1:00:30] 此外,每个 map 都必须完全独立。必须是呃……函数式的、纯函数式的函数,只查看它们的参数,别的什么都不看。你知道,这就像是一种限制。而事实证明,许多人想要运行长得多的流水线,涉及许许多多不同种类的处理。而使用 MapReduce,你必须从多个——以及 MapReduce。不同的 map 产生的作业中拼凑起来。而更先进的系统,我们将在本课程后面讨论,在允许你指定完整的计算流水线方面要好得多,而且它们会做优化。

[1:01:09] 框架实现了你必须做的所有事情。以高效得多的方式组织复杂得多的东西。优化复杂得多的计算。你的问题。所以在论文中,他们区分了 mapper 和 map 函数。我猜那就是——就像运行 map 的进程。那……以及欢迎那些正在——从程序员的角度来看,它只关乎 map 和 reduce。

[1:01:43] 从我们的角度来看,它将关乎工作进程。以及作为 MapReduce 框架一部分的工作服务器,还有许多其他东西。把它们从 produce 函数中区分出来。所以——嗯,是的,从我们的角度来看,我们非常关心这如何由周围的框架来组织。这是把所有这些分布式的东西剥离掉之后的程序员视角。嗯。是的?谢谢。抱歉,我得……

[1:02:21] 再说一遍。抱歉,你是在本地 emit 吗?哦,你是说 emit 的数据去哪里了?谢谢。好的,所以有两个问题。一个是……当你调用 emit 时,数据会发生什么?另一个是这些函数在哪里运行。所以,谢谢。嗯。实际的答案是,首先,这些东西在哪里运行?有若干台,比如说,一千台服务器。实际上,这里应该看的是论文中的图一。

[1:02:59] 嗯,尽管在现实世界中,这下面有一些大型服务器集合。而且嗯。我们或许称它们为工作服务器或工作者。而且。还有一个单一的主服务器在组织整个计算。这里发生的情况是,主服务器知道有一定数量的输入文件,你知道,5,000个输入文件。并且它将 map 的调用分派给不同的工作者。所以它会向工作者七发送消息说,请在某某输入文件上运行这个 map 函数。

[1:03:39] 然后那个 worker 函数,它是 MapReduce 的一部分,对 MapReduce 了如指掌,那么,嗯,读取文件,读取输入,不管怎样,无论是哪个输入文件。并以文件名值作为参数调用这个 map 函数。然后那个 worker 进程。就是实现 emit 的东西。每当 map 调用 emit 时,worker 进程。就会把这些数据写入本地磁盘上的文件。

[1:04:11] 那么 map 的 emit 会发生什么?它们会在 map worker 的本地磁盘上产生文件,这些文件累积了在该 worker 上运行的 map 所产生的所有键和值。嗯,所以在 map 阶段结束时,我们剩下的是所有那些 worker 机器,每一台都拥有在该 worker 机器上运行的某些 map 的输出。然后 MapReduce worker 会安排把数据移动到 reduce 需要它的地方,而且由于我——在一个典型的大型计算中,这次 reduce 的汇集将需要所有提到键 A 的 map 输出,但结果会是,你知道,这是一个简单的例子,但一般来说,很可能每一次 map 调用都会产生许多键,包括键 A 的一些实例。

[1:05:13] 所以通常,为了按顺序进行,在我们甚至能够运行这个 reduce 函数之前,MapReduce 框架,也就是运行在我们一千台服务器之一上的 MapReduce worker,将不得不去和另外一千台服务器中的每一台通信,说:“看,我要为键 A 运行 reduce,请查看你磁盘上存储的中间 map 输出,把键 A 的所有实例都找出来,并通过网络发送给我。”所以 reduce worker 会这么做。它会从每个 worker 那里获取。

[1:05:44] 它负责的键的所有实例,也就是主服务器告诉它要负责的那些。一旦它收集了所有那些数据,它就可以调用 reduce。而 reduce 函数本身会调用 reduce emit,这与 map 中的 emit 不同。reduce emit 所做的是把输出写入一个文件。写入 Google 使用的一种集群文件服务中。所以这里有一件我还没提到的事。

[1:06:15] 嗯,我还没提到输入存放在哪里。以及输出存放在哪里。它们都是 vial。嗯,因为对于任何一块输入,我们都希望能够灵活地在任何 worker 服务器上读取任何一块输入。这意味着我们需要某种网络文件系统来存储输入数据。嗯,所以确实,论文谈到了这个叫做 GFS 的东西,即 Google File System。

[1:06:48] 嗯,GFS 是一个集群文件系统。而 GFS 实际上运行在运行 MapReduce 的完全相同的一组工作服务器上。输入 GFS 会自动地,当你,你知道,它是一个文件系统,你可以读写文件。它只是自动地将你存储在其上的任何大文件分割成 64 兆字节的块,分布到许多服务器上。所以如果你写入,如果你有 10 太字节的抓取网页内容,然后你只是将它们写入 GFS,即使作为一个单一的大文件,GFS 也会自动将如此大量的数据分割成 64 千字节的块,均匀分布在所有 GFS 服务器上,也就是说,Google 拥有的所有服务器上。

[1:07:32] 那太棒了,这正是我们需要的。如果我们随后想运行一个以整个抓取网络为输入的 MapReduce 作业,数据已经以均匀分布在所有服务器上的方式存储好了。这意味着,嗯,map 工作器,你知道,我们将要启动——如果我们有一千台服务器,我们将启动一千个 map 工作器,每个读取输入数据的千分之一,并且它们能够从一千个 GFS 文件服务器并行读取数据。

[1:08:02] 那就得到了……一个巨大的总读取吞吐量。你知道,一千台服务器的读取吞吐量。是的。谢谢。运行 map。所以你是不是在想,也许 Google 有一组物理机器运行 GFS,另一组独立的物理机器运行 MapReduce 作业。说“我可以要两个吗?”

[1:08:37] 好的。它们不一定是。——对,所以问题是,这里的这个箭头实际上涉及什么。嗯,这个问题的答案实际上多年来随着 Google 整个系统的发展而有所变化。你知道,在最一般的情况下,如果我们有大文件存储在某个大型网络文件系统中。比如,你知道,GFS 有点像 AFS,你可能在 Athena 上用过。你需要去跟某个集合通信,你的数据分散在一个大的服务器集合上,你必须通过网络去跟那些服务器通信来取回你的数据。

[1:09:13] 嗯,在那种情况下,这个箭头可能代表的是——谢谢——map,MapReduce 工作进程必须离开去通过网络与存储其输入部分的正确的 GFS 服务器或可能多个服务器通信,并通过网络将其取到 MapReduce 工作机器上以便进行 map。这当然是最一般的情况。而这最终也是 MapReduce 实际工作的方式。然而在这篇论文的世界里,如果你那样做,那将是大量的网络通信。

[1:09:47] 你说的是 10 太字节的数据,然后我们必须将 10 太字节的数据通过他们的数据中心网络传输,这……你知道,数据中心网络以每秒千兆比特运行,但传输数十太字节的数据仍然需要大量时间。谢谢。为了尝试,而且确实在这篇论文的世界里,在 2004 中,他们的 MapReduce 系统中最受限的瓶颈是网络吞吐量。因为他们运行在一个网络上,如果你读到评估部分的话,他们的网络,他们的网络是嗯……

[1:10:23] 他们有数千台机器,不管怎样,他们会收集机器,他们把机器插入,你知道,每个机架的机器插入该机架的以太网交换机之类的。但然后,你知道,它们都需要相互通信。但有一个根以太网交换机,所有机架以太网交换机都与它通信。而这个,你知道,所以如果你随便选一个 MapReduce 工作器和某个 GFS 服务器,很可能至少有一半时间,它们之间的通信必须经过这一个根交换机。他们的根交换机只有一定的总吞吐量,我忘了是多少,呃……你知道,某个每秒千兆比特数。

[1:11:07] 嗯,总之,我忘了具体数字,但当我做除法时,即把根交换机可用的总吞吐量除以他们在论文实验中使用的约 2,000 台服务器。我得到的是,每台机器在根交换机或总网络容量中的份额只有 50 兆比特每秒,在他们的设置中。字幕由 Amara.org 社区提供 所以每台机器 50 兆比特每秒。

[1:11:39] 这看起来可能很多,50 兆比特,天哪,数百万又数百万。但与比如磁盘或 CPU 的运行速度相比,它实际上相当小。所以这个,在他们的网络中,这 50 兆比特每秒是一个巨大的限制。他们在论文描述的设计中真的绞尽脑汁避免使用网络。他们玩了一堆把戏来尽可能避免通过网络发送东西。其中之一是——他们运行 GFS。

[1:12:12] 服务器。以及 MapReduce 工作器在同一组机器上。这样他们有一千台机器——他们运行 GFS,在这一千台机器上实现他们的 GFS 服务,并在同一千台机器上运行 MapReduce。然后当 master 在分割 map 工作并分发给不同工作器时,它会巧妙地——当它——我要进入下一个问题了——即将运行 map 时,那个 map 将从输入文件一读取,它会从 GFS 找出哪个服务器实际上在其本地磁盘上持有输入文件一。

[1:12:50] 然后它会——将那个输入文件的 map 发送给同一台机器上的 MapReduce 软件。这样默认情况下,这个箭头实际上是从本地磁盘的本地读取,不涉及网络。而你知道,取决于故障或负载或其他什么,它不能总是这样做。但几乎所有的 map 都会在存储数据的同一台机器上运行,从而节省了他们否则将不得不等待输入数据通过网络传输的大量时间。

[1:13:21] 嗯,他们玩的下一个把戏是,正如我之前提到的,map 将其输出存储在运行 map 的机器的本地磁盘上。所以,同样,存储 map 的输出不需要网络通信,至少因为输出存储在磁盘上。然而,我们确信,无论如何,为了将 MapReduce 定义中所有的方式分组在一起,为了将给定键关联的所有值分组在一起,并将它们传递给某个机器上的单次调用来产生结果,这将需要网络通信。

[1:13:59] 我们要——你知道,我们想——我们需要——我们就是 所有的 A,并给它们一台机器,必须通过网络移动。所以这个 shuffle,这个键的移动,从这种,你知道,最初由 Rowe 存储在运行 map 的同一台机器上。我们本质上需要它们按列存储在将要负责 reduce 的机器上。这种从行存储到本质上的列存储的转换被称为,论文称之为 shuffle。而且它确实需要移动每一条数据。

[1:14:30] 通过网络。从产生它的 math 到我们需要的 reduce。这就是……嗯,MapReduce 中昂贵的部分。是的。他们为什么不?做一个能运行类似你会有的东西,保持你的……就像你已经有的那样。选择一个,然后你会等一整夜。你说得对,你可以想象一个不同的定义,其中有一个更流式的 reduce。我不知道,我没仔细想过。我不知道为什么。那是否可行。当然就程序员接口而言,就像如果目标,他们的首要目标真的是,能够使编程变得容易。

[1:15:11] 由那些完全不知道系统里发生了什么的人。所以可能这个规范,这真的是 reduce 函数的样子。在 C++ 之类的语言中。就像这个的流式版本现在看起来开始,我不知道它看起来怎样。可能不是这么简单。但你知道,也许可以那样做。确实,许多现代系统人们已经变得更加复杂。用作为 MapReduce 后继者的现代事物。它们确实经常涉及处理数据流,而不是这种非常批处理的方法。这是批处理方式,因为我们等到获得所有数据然后处理它。

[1:15:55] 所以首先,你必须有一个有限输入的概念,对吧?而现代系统确实经常使用流。并且……能够因此利用一些效率。谢谢。但不是 MapReduce。谢谢。嗯……好的,所以这就是 shuffle 发生所有网络流量的点,这实际上可能是海量数据。所以如果你考虑排序,如果你在排序,排序的输出与排序的输入大小相同。所以这意味着如果你的输入是 10 TB 的数据,而你正在运行排序,你此时正在通过网络移动 10 TB 的数据。

[1:16:37] 而你的输出也将是 10 TB,所以这是——相当多的数据,确实对于许多 map 产生的作业来说是这样,尽管不是全部。在这些阶段显著减少数据量。我……有人提到,哦,如果你想将 reduce 的输出馈送到另一个 MapReduce 呢?确实,这通常是人们想做的。无论如何,reduce 的输出可能非常巨大,比如排序或网页索引。它产生的输出是在 10 TB 输入上。reduce 的输出再次将是 10 TB。所以 reduce 的输出也存储在 GFS 上。

[1:17:10] 而系统会——你知道,reduce 只会产生这些键值对,但是,谢谢。MapReduce 框架会将它们收集起来并写入 GFS 上的巨大文件。嗯,所以还需要另一轮网络通信,将每个 reduce 的输出送到存储该产出的 GFS 服务器。你可能认为他们可以……玩同样的把戏,将输出存储在恰好运行了执行 reduce 的 MapReduce worker 的 GFS 服务器上。

[1:17:48] 也许他们确实那样做了,但因为 GFS 除了为性能拆分数据外,还保留两到三个副本以实现容错。这意味着无论如何,你需要通过网络将一份数据副本写入不同的服务器。所以这里有很多网络通信,这里也有一堆。嗯,正是这种网络通信真正限制了……2004 中的吞吐量。嗯,在 2020 中,因为这种网络安排对人们在数据中心想做的许多事情来说是一个如此限制性的因素。

[1:18:22] 现代数据中心网络在根部的速度比这快得多。嗯,你今天可能看到的一个典型数据中心网络实际上有许多根,而不是所有东西都必须经过的单个根交换机,你可能有——许多根交换机,每个机架交换机都与这些复制的根交换机中的每一个有连接,流量在根交换机之间分流。所以现代数据中心网络有远更多的网络吞吐量,嗯,正因为如此,实际上,现代——我认为谷歌几年前就停止使用 MapReduce 了,但是嗯,在他们停止使用它之前。

[1:19:01] 现代 MapReduce 实际上不再尝试在数据存储的同一台机器上运行 map。他们乐于从任何地方加载数据,因为他们只是假设网络极快。好的。MapReduce 的时间到了。我们下周结束时有一个实验,你将编写自己的简化版 MapReduce。所以,玩得开心。周四见。

查看英文原始字幕

[0:01] All right, let's get started. This is 6824, distributed systems. Um, Thank you. So I'd like to start with just a brief explanation of what I think a distributed system is. Thank you. The core of it is a set of cooperating computers that are communicating with each other over network to get some coherent task done. The kinds of examples that we'll be focusing on in this class are things like storage for big websites, or big data computations such as MapReduce, Um, And also somewhat more exotic things like peer to peer file sharing.

[0:43] Those are all just examples of the kinds of case studies we'll look at. Um, And the reason why all this is important is that a lot of critical infrastructure out there is built out of distributed systems. Infrastructure that requires more than one computer to get its job done or sort of inherently needs to be spread out physically. Um. So the reasons why people build this stuff, First of all, before I even-- talk about distributed systems, I just want to remind you that If you're designing a system, you need to solve some problem, if you can possibly solve it, on a single computer.

[1:17] you know, without building a distributed system, you should do it that way. And there's many, many jobs you can get done on a single computer, and it's always easier. So distributed systems, you should try everything else before you try building distributed systems 'cause they're not simpler. So the reason why people are driven to use lots of cooperating computers are They need to get high performance. And the way to think about that is they want to get, achieve some sort of parallelism. Lots of CPUs, lots of memories, lots of disk arms moving in parallel.

[1:54] Another reason why people build this stuff is to be able to tolerate faults. Wow. . have two computers do the exact same thing. If one of them fails, you can cut over to the other one. Another is that some problems are just naturally spread out in space. Um, You want to do interbank transfers of money or something. Bank A has this computer in New York City, and Bank B has this computer in London.

[2:25] you know, you just have to have some way for them to talk to each other and cooperate in order to carry that out. So there's some natural sort of physical reasons systems that are inherently physically distributed, And the final reason that people build this stuff is in order to achieve some sort of security goal. So often by, if there's some code you don't trust, or you need to interact with somebody, They may be malicious or maybe their code has bugs in it. So you don't want to have to trust it. You may want to split up the computation so, you Your stuff runs over there on that computer, my stuff runs here on this computer, and they only talk to each other.

[3:03] to some sort of narrow, narrowly defined network protocol. So we may be worried about security, And that's achieved by splitting things up into multiple computers so that they can be isolated. Um. The-- Most of this course is going to be about performance and fault tolerance, although the other two often work themselves in by way of the sort of constraints on the case studies that we're going to look at. Um, You know, all the distributed systems of these problems are, because they have many parts and the parts execute concurrently, because there are multiple computers.

[3:42] You get all the problems that come up with concurrent programming, all the sort of complex interactions and weird timing dependent stuff. And that's part of what makes distributed systems hard. Another thing that makes... distributed systems hard is that Because again you have multiple pieces plus a network. you can have very unexpected failure patterns that is If you have a single computer, it's usually the case that either the computer works or maybe it crashes or suffers a power failure or something. But it pretty much either works or doesn't work.

[4:12] Distributed systems made up of lots of computers, you can have partial failures. That is, some pieces stop working, other pieces continue working. Or maybe the computers are working, but some part of the network is broken or unreliable. um So partial failures is another reason why uh... distributed systems are hard. So this is sort of basic challenges. Bye. Thank you. Thank you.

[4:44] Bye. Subtitles by the Amara.org community Thank you. Thank you. And a final reason why it's hard is that, you know, the original reason to build a distributed system is often to get higher performance. to get 1,000 computers worth of performance, or 1,000 disc arms, worth of performance. But it's actually very tricky to obtain that thousand X speed up with a thousand computers. There's often a lot of roadblocks thrown in your way. Um, Hello.

[5:15] Thank you. Thank you. It often takes a bit of careful design to... make the system actually give you the performance you feel you deserve. So solving these problems, of course, can be all about, you know, addressing these issues. Um, The reason to take the course is because often the problems and the solutions are quite just technically interesting and They're hard problems. For some of these problems, there's pretty good solutions known for other problems They're not such great solutions, no.

[5:46] Distributed systems are used by a lot of real world systems out there, big websites often involved. you know, vast numbers of computers that are, you know, put together as distributed systems. When I first started teaching this course, It was. distributed systems were something of an academic curiosity. You know, people thought, "Oh, you know At a small scale, they were used sometimes, and people felt that, oh, someday they'd be... might be important. but now particularly driven by the rise of giant websites.

[6:17] that have you know, vast amounts of data and entire warehouses full of computers, distributed systems in the last 20 years have gotten to be Very-- seriously important part of computing infrastructure. Okay. This means that there's been a lot of attention paid to them, a lot of problems have been But there's still quite a few unsolved problems. So if you're a graduate student or you're interested in research, There's a lot of problems yet to be solved in distributed systems You could look into his research.

[6:49] And finally, if you like building stuff, This is a good class because it has a lab sequence in which you'll construct some fairly realistic distributed systems focused on performance and fault tolerance. So you've got a lot of practice. building distributed systems and making them work. All right. Let me talk about course structure a bit before I... get started on real technical content. You should be able to find the course website.

[7:20] using Google. And on the course website is the lab assignments course schedule, and also linked to a Piazza where you can post questions, get answers. Um, The course staff, I'm Robert Morris, will be giving the lectures. I also have four TAs. You guys want to stand up and show your faces? Um, Thank you. The TAs are experts at in particular at solving the labs, They'll be holding office hours, so if you have Questions about the labs, you should go to office hours.

[7:54] or you could post questions to Piazza. Um, Thank you. The course has a couple of important components. Um, One is his lectures. There's a paper for almost every lecture. Thank you. Thank you. There's two exams. Thank you. Thank you. Thank you. Bye. There's the labs, programming labs, and Um, there's an optional final project that you can do instead of one of the labs.

[8:27] Thank you. Subtitles by the Amara.org community The lectures will be about big ideas in distributed systems. There will also be a couple of lectures that are more about sort of lab programming stuff. A lot of the lectures will be taken up by case studies, a lot of the way that I sort of try to bring out the um, content of distributed systems is by looking at papers some academic, some written by people in industry, describing real solutions to real problems.

[9:04] Um, These lectures actually would be videotaped. and I'm hoping to post them online so that you can that if you're not here, or you want to review the lectures, you'll be able to look at the videotape lectures. Amen. The papers, again, there's one to read per week. Most of them are research papers. Some of them are classic papers. Like today's paper, which I hope some of you have read on MapReduce. It's an old paper, but it was the beginning of, it spurred an enormous amount of interesting work, both academic and in the real world. So some are classic and some are more recent papers.

[9:38] sort of talking about more up-to-date research, what people are currently worried about. And from the papers, I'll be hoping to tease out what the basic problems are, what ideas people have had that might or might not be useful in solving distributed system problems, Um, We'll be looking at sometimes at implementation details in some of these papers. Because a lot of this has to do with actual construction of of software-based systems. And we're also going to spend a certain amount of time looking at evaluations. people evaluating how fault tolerant their systems by measuring them or people measuring how much performance or whether they got performance improvement at all.

[10:14] Um, So I'm hoping that you'll all read the papers before coming to class. The lectures are... maybe not gonna make as much sense if you haven't already read the lecture, because there's not enough time to both explain all the contents of the paper and have a sort of interesting reflection on what the paper means. online class you really gotta be papers before coming to class and hopefully one of the things you learn in this class is how to read a paper rapidly and efficiently, and skip over the parts that maybe aren't that important sort of focus on teasing out the important ideas.

[10:50] On the website, there's for every link to by the schedule, there's a question. that you should submit an answer for for every paper. I think the answers are due at midnight. And we also ask that you submit a question you have about the paper. Um, to the website in order both to give me something to think about as I'm preparing the lecture and if I have time I'll try to answer at least a few of the questions by email. And the question and the answer for each paper are due midnight. the night before.

[11:21] There's two exams, there's a midterm exam in class, I think on the last class meeting before, uh Spring break. Um, and there's a final exam during final exam week at the end of the semester. The exams are going to focus mostly on papers and the labs. and probably the best way to prepare for them as well as attending lecture and reading the papers. um a good way to prepare for the exams is to look at old exams.

[11:52] 20 years of old exams and solutions. And so you look at those and sort of get a feel for what kind of questions that I like to ask. And indeed, because we read many of the same papers, Inevitably, I ask questions each year that can't help but resemble questions asked in previous years. Thank you. The labs, there's four programming labs. The first one of them is due Friday next week. um They're...

[12:23] Thank you. Lab one is a... Thank you. A simple MapReduce lab. to implement your own version of the paper. in which I'll be discussing in a few minutes. Um, Lab two. involves using a technique called raft in order to get fault, in order to, sort of allow, in theory, allow any system to be made fault tolerant by replicating it and having this raft technique. manage the replication and manage sort of automatic cut over if there's a failed if one of the replicated servers fails.

[12:59] So this is RAF for fault tolerance. Um. Thank you. Subtitles by the Amara.org community *kiss* In lab three, you'll use your raft implementation in order to build a fault tolerant key value server. Thank you. Amen. Thank you. It'll be replicated and fault tolerant. And in lab four, you'll take your replicated key value server and clone it into a number of independent groups. and you'll split the data Um, in your key value storage system across all of these individual replicated groups to get parallel speed up.

[13:37] by running multiple replicated groups in parallel and you'll also be responsible for moving the various chunks of data between different servers as they come and go. without dropping any balls. what's often called a sharded, Bye. key values service. Bye. you Sharding refers to splitting up the data, partitioning the data. among multiple servers in order to get parallel speedup.

[14:10] um Thank you. If you want, instead of doing lab four, You can do a project of your own choice. And the idea here is if you have some idea for a distributed system you know, in the style of... some of the distributed systems we talk about in the class, if you have your own idea that you want to pursue, and you like to build something and measure whether it worked Explore your idea. you can do a project. Um, And so for a project, you'll pick some teammates because we require that projects are done and teams of two or three people.

[14:45] Nam. So like some teammates and send your project idea to us and we'll think about it and say yes or no and maybe give you some advice. um, And then if you go ahead and do, if we say yes, and you want to do a project, you do that instead of Lab 4, and it's do. at the end of the semester. You know, you'll... you should do some, uh, design work and build a real system, and then in the last day of class, you'll demonstrate your system. as well as handing in a short... sort of written report to us about what you built. And I posted on the website some some ideas which might or might not be useful for you to sort of spur thoughts about what projects you might build, but really the best projects are one where you have a good idea, for the project. And the idea is if you want to do a project, you should choose an idea that's sort of in the same vein as the systems that we're talk about in this class.

[15:40] Okay, back to labs. The lab grades that we give you, you hand in your lab code, and we run some tests against it, You're graded based on how many tests you pass. We give you all the tests that we use, so there's no hidden tests. So, If you influence the lab and it reliably passes all the tests, then chances are good, unless there's something funny going on, which there sometimes is. Chances are good that if your code passes all the tests when you run it, it'll pass all the tests when we run it. and you'll get a full score. So hopefully there'll be no mystery about what score you're likely to get.

[16:13] on the labs. Um, Let me warn you that Debugging these labs can be time consuming. Because they're distributed systems, and have a lot of concurrency and communication, Um, sort of strange, difficult to debug errors can crop up. You really ought to start the labs early. Don't leave them. A lot of trouble if you leave the labs to the last moment. You got to start early. If you're-- problems, please come to the TA's office hours.

[16:44] and please feel free to ask questions. about the labs on Piazza. And indeed, I hope if you know the answer that you'll answer people's questions on Piazza as well. All right. Any questions about the mechanics of the course? Yes? Bye. Yeah. Thank you. So the question is, how do these things factor into grade? I forget, but it's all on the...

[17:18] It's on the website under-- something. Um. I think it's the labs are the single most important. component. Thank you. Okay. Thank you. Um... All right, so this is a course about infrastructure. for applications. And so all through this course, there's going to be a sort of split in the way I talk about things between applications, which are sort of other people, the customer, somebody else writes.

[17:49] The applications are going to use the infrastructure that we're thinking about in this course. And so the kinds of infrastructure that tend to come up a lot. Thank you. Thank you. are storage Thank you. communication Thank you. and computation. And we'll talk about systems that provide all three of these kinds of infrastructure.

[18:19] Um, the storage Turns out that storage is going to be the one we focus most on because it's a very well-defined and useful abstraction. And thank you. usually fairly straightforward abstractions. So people know a lot about how to use and build storage systems and how to build sort of replicated fault tolerant high performance distributed implementations of storage. We'll also talk about some of our computation systems, like MapReduce for today.

[18:50] is a computation system. Um, And we will talk about communication some, but mostly from the point as a tool that we need to use to build distributed systems. Like computers have to talk to each other, over a network, you know, maybe you need reliability or something. And so we'll talk a bit about but we're actually mostly... consumers of communication. Um, If you want to learn about communication, systems as or how they work, that's more the topic of 6829. So for storage and computation, A lot of our goal is to be able to discover abstractions, Um, ways of simplifying the interface to these, Storage and computation distributed storage and computation infrastructure so that it's easy to build applications on top of it.

[19:41] And what that really means is that we need to, we'd like to be able to build abstractions that hide the distributed nature of these. of these systems. So the dream, which is rarely fully achieved, but the dream would be to be able to build an interface, That looks to an application as if it's a non distributed storage system just like a file system or something that everybody already knows how to program and has a pretty simple model semantics. We'd love to be able to build interfaces that look and act just like non-distributed, storage and computation systems, but are actually-- you know, vast, extremely high performance, fault tolerant, distributed systems underneath.

[20:23] Um. So we'd love to have abstractions. Thank you. Subtitles by the Amara.org community Thank you. And as you'll see as the course goes on, we sort of, you know only part of the way there. It's rare that you find an abstraction for a distributed version of storage or computation that has simple behavior, behaves just like Um, the non-distributed version of storage that everybody understands. People are getting better at this and...

[20:54] um We're going to try to study the ways in what people have learned about. building such abstractions. Okay. What kind of, what kind of, Topics show up as we're considering these abstractions. The first one, the first topic, general topic that we'll see a lot is in a lot of the systems we look at, have to do with implementation. Thank you. um So, for example, the kind of tools that you see a lot for for ways people learn how to build these systems are things like remote procedure call, whose goal is to mask the fact that we're communicating over an unreliable network.

[21:38] um Another kind of implementation A topic that we'll see a lot is threads. which are a programming technique, that allows us to harness multi-core computers, but maybe more important for this class, Threads are a way of structuring concurrent operations. in a way that's hopefully simplifies the programmer view of those concurrent operations. Um, And because we're gonna use threads a lot, it turns out we're gonna need to also just from an implementation level, spend a certain amount of time thinking about concurrency control, things like locks.

[22:18] Um. you Thank you. And the main place that these implementation ideas will come up in the class, there will touched on in many of the papers, but you're going to come face to face with all of this in a big way in the labs. You need to build distributors. you know, do the programming for distributed systems. These are like a lot of the sort of important tools beyond just sort of ordinary programming, Um, These are some of the critical tools that you'll need to use. I'm back. to build distributed systems.

[22:50] Another big topic that comes up in all the papers we're going to talk about is performance. Thank you. Bye. Thank you. Thank you. Um, Usually the high level goal of building a distributed system is to get what people call scalable speedup. So we're going to look in for scalability. And what I mean by scalability or scalable speedup is that If I have some problem that I'm solving with one computer, and I buy a second computer to help me execute my problem.

[23:30] If I can now solve the problem in half the time, or maybe solve twice as many problem instances. you know, per minute. on two computers as I had on one, then That's an example of scalability. Sort of. two times the computers or resources, um gets me two times the performance or throughput. And this is a huge hammer. If you can build a system that actually has this behavior, Namely that If you increase the number of computers you throw at the problem by some factor, You get that factor, more throughput, more performance.

[24:14] out of the system. That's a huge win. Because You can buy computers with just money. Right? Whereas if in order to get the alternative to this, Um, is that in order to get more performance, you have to pay programmers to restructure your software to get better performance, to make it more efficient, to apply some sort of specialized techniques, better algorithms or something. If you have to pay programmers, the fix your code to be faster.

[24:44] an expensive way to go. We'd love to be able to just, oh, buy a thousand computers instead of 10 computers and get You know, 100 times more throughput. That's fantastic. And so this sort of scalability idea is a huge idea in the backs of people's heads when they're like building things like big websites that run on a you know, building full of computers. If the building full of computers is there to get a sort of corresponding amount of data performance. you have to be careful about the design in order to actually get that performance. Um, So, often the way this looks when we're looking at diagrams or writing diagrams in this course is that That's supposing we're building a website.

[25:26] Ordinarily, you might have a website that you know, has a HTTP server, or let's say it has some has some users. um, running web browsers, And they talked to... you know, web server running Python or PHP or whatever, Sort of web server. And the web server talks to some kind of database. Um, You know, when you have one or two users, have one computer running both, or maybe a computer for the web server and a computer from the database, Maybe all of a sudden you get really popular and you You know, 100 million people sign up for your service.

[26:10] Right? How do you... No. How do you fix your-- you certainly can't-- support millions of people on a single computer, Um, except by extremely careful labor intensive optimization. Um, but you don't have time for. So, Typically the way you're going to speed things up, the first thing you do is buy more web servers and just split the users so that you know, half your users or some fraction of the user go to web server one and the other half You send them to web server two.

[26:40] and because maybe you're building I don't know what, Reddit or something, where all the users need to see the same data ultimately, you have all the web servers talk to the back end. And maybe you can keep on adding web servers for a long time here. Thank you. Um, Thank you. And so this is a way of getting parallel speed up on the web server code. You know, if you're running PHP or Python, maybe it's not too efficient. Um, Uh, as long as each individual web server doesn't put too much load on the database, you can add a lot of web servers.

[27:13] before you run into problems. But. this kind of scalability is rarely infinite, unfortunately. um Certainly not without serious thought. And so what tends to happen with these systems is that at some point after you have 10 or 20 or 100 web servers all talking to the same database, Now all of a sudden the database starts to be a bottleneck. and adding more web servers no longer helps. So it's rare that you get full scalability through sort of infinite numbers of adding infinite numbers of computers.

[27:45] At some point you run out of gas because The place at which you are adding more computers is no longer the bottleneck. by having lots and lots of web servers, we basically move the bottleneck Um, I think it's limiting performance from the web servers to the database. Um, And at this point, actually, you almost certainly have to do a bit of design work. because It's rare that you can take, that there's any straightforward way to take a single database and sort of refactor things. with it for. you can take data sorted in a single database and refactor it so it's split over multiple databases.

[28:21] Um, but it's often a fair amount of work. and Because it's awkward, but many people actually need to do this. Um, We're going to see a lot of examples in this course in which the distributed system people talking about is a storage system. because the authors were running You know, something like a big website that ran out of gas on a single database or storage servers. Um, Anyway, so the Scalability story is we love to build systems that scale this way, but um you know it's hard to make it, or it takes work often, design work, push this idea infinitely far.

[29:04] Amen. Thank you. Thank you. Okay, so. Another big topic that comes up a lot is fault tolerance. Thank you. . If you're building a system with a single computer in it, well, A single computer often can stay up for years. Like, I have servers in my office that have been up for years without crashing. Um, You know, the computer's pretty reliable, the operating system's pretty reliable, Apparently the power in my building is pretty reliable. So it's not uncommon to have single computers that just stay up for amazing amounts of time.

[29:44] However, If you're building systems out of thousands of computers, then even if each computer can be expected to stay up for a year, With a thousand computers that means you're gonna have like about three computer failures per day. And in your set of computers. solving big problems with big distributed systems turns sort of very rare fault tolerance, very rare failure problems, into failure problems that happen just all the time. In a system with a thousand computers, there's almost certainly always something broken. There's always some computer that's either crashed or mysteriously running incorrectly or slowly or doing the wrong thing.

[30:25] Or maybe there's some piece of the network, like with a thousand computers, We got a lot of network cables. and a lot of network switches. You know, there's always some network cable that somebody stepped on and is unreliability, or network cable that fell out, or some network switch whose fan is broken and the switch overheated and failed. There's always some little problem somewhere in your building-sized um, distributed system. So Big scale turns problems from very rare events, you really don't have to worry about that much, into just constant problems.

[30:57] The... failure has to be really, or the response, the masking of failures, the ability to perceive about failures just has to be built into the design. because there's always failures. Um... And, you know, as part of building, you know, convenient abstractions for application programmers, We really need to be able to build infrastructure that as much as possible hides the failures from application programmers or masks them or something. so that every application programmer doesn't have to have a complete complicated story for all the different kinds of failures that can occur.

[31:32] Um, there's a bunch of different notions that you can have about what it means to be fault tolerant. about a little more. but exactly what we mean by that. And we'll see a lot of different flavors, but among the more common ideas you see, one is availability. Thank you. Amen. So, you know, some systems are designed so that under, some certain kinds of failures, not all failures, but certain kinds of failures, the system will keep operating despite the failure while providing undamaged service.

[32:15] Uh, the same kind of service it would have provided, even if there had been no failure. So some systems are available in that sense, So if you build a replicated service that maybe has two copies, You know, if one of the replicas replica servers fail fails, maybe the other server can continue operating They both fail, of course, you can't. You know, you can't promise. Um. availability in that case. So available systems usually say, well, under a certain set of failures, We're going to continue providing service. We're going to be available.

[32:48] More failures than that occur. It won't be available anymore. Thank you. Another kind of fault tolerance you might... you might have or in addition to availability or by itself is recoverability. Thank you. Thank you. Thank you. And what this means is that if something goes wrong, maybe the service will stop working. That is it all. simply stopped responding to requests, Um, and it'll wait for someone to come along and repair whatever went wrong, but after the repair occurs, the system will be able to continue as if nothing bad had gone wrong.

[33:23] So this is sort of a weaker requirement than availability, because here we're not going to do anything while until the failed component has been repaired, But the fact that we can get up get going again without, you know, but... without any loss of correctness, is still a significant requirement. It means, you know, recoverable systems typically need to do things like save their latest date on disk or something where they can get it back you know, after the power comes back up. Um, And even among available systems, In order for a system to be useful in real life, Usually what the way available systems are specced is that They're available until Some number of failures have happened. If too many failures have happened, an available system will stop working or will stop responding at all, But when enough things have been repaired, it'll continue operating. So a good available system will sort of be recoverable as well in the sense that if too many failures occur,

[34:26] um It'll stop answering, but then we'll continue correctly after that. Um, So this is what we love to hear. This is what we'd like to obtain. The biggest hammer, we'll see a number of approaches to solving these problems. I said, sort of Two things that are the most important. tools we have in this department. One is non-volatile storage. so that, you know, something crashed, power failed, or whatever, Maybe there's a building-wide power failure. We can use non-volatile storage like hard drives or flash or solid state drives or something to sort of store a checkpoint or a log the uh state of the system and then when the power comes back up or somebody repairs our power supply, who knows what, we'll be able to read our latest state off the hard drive and continue from there.

[35:22] So. So one tool is sort of non-volatile storage. And the management of non-volatile storage is something that comes up a lot, because non-volatile storage tends to be expensive to update. And so a huge amount of the sort of nitty-gritty of building sort of high performance fault-tolerant systems is in clever ways to avoid having to write the non-volatile storage too much. In the old days and even today you know, what writing non-volatile storage meant was, moving a disc arm and waiting for a disk platter to rotate.

[35:58] both of which are agonizingly slow. on the scale of, you know, 3 gigahertz microprocessors. With things like flash. Life's quite a bit better, but still requires a lot of thought to get good performance out of it. And the other big tool we have for fault tolerance is replication. Thank you. and the management of replicated copies is sort of tricky You know, that sort of problem lurking in any replicated system where we have two servers each with a supposedly identical copy of the system state.

[36:32] Um, The key problem that comes up is always that the two replicas will accidentally drift out of sync and will stop being replicas. And this is just-- you know, at the back of every design that we're gonna see for using replication to get fault tolerance. And Lab 2, and that's what you're all about. management of replicated copies for fault tolerance. Um. As you'll see, it's pretty complex. Um, A final topic, final cross-cutting topic, um is consistency.

[37:11] Thank you. Thank you. So as an example of what I mean by consistency supposing we're building a distributed storage system and it's a key value service so it just supports. two operations, maybe there's a put operation, and you give it a key, and a value and the storage system sort of stashes away the value under as the value for this key, so it maintains just a big table of keys and values. And then there's a get operation. the client sends it a key and the storage service is supposed to respond with the value that's stored for that key.

[37:51] And this is kind of the When I can't think of anything else as an example of a distributed system, I'll whip uh, key value services. And they're very useful, right? They're just sort of the fundamental Um, simple version of a storage system. So. Of course if you're an application programmer. It's helpful if... These two operations kind of have meanings attached to them. You can go look in the manual and the manual says you know, what it what it means, what you'll get back if you call get.

[38:23] right, and sort of what it means for you to call put So it would be great if there was some sort of spec for what they meant, otherwise, like, How can you possibly write an application without a description of what Pudding getters are supposed to do. Um, And this is the topic of consistency. And the reason why it's interesting in distributed systems is that Um. both for performance and for fault tolerant reasons, fault tolerance reason, we often have more than one copy of the data floating around. So, you know, in a non-distributed system where you just have a single server with a single table, there's often, although Not always.

[39:02] There's often relatively no ambiguity about what put and get could possibly mean intuitively. You know, what put means is update the table, and what get means is just, get me the version that's stored in the table, Um, But in a distributed system, where there's more than one copy of the data, due to replication or caching or Who knows what? There may be lots of different versions um of this key value pair floating around. Like if one of the replicas, you know, supposing some client issues a put, and You know, there's-- two copies of the The server, so they both have a key value table.

[39:46] Right, and maybe key one has value 20 on both of them. Thank you. and then some client issues a put. We have a client over here. and it's gonna send a put, it wants to update the value of one to be 21. Maybe it's counting stuff in this Key value server, so it sends a put Thank you. with key one and value 21, it sends it to the first server and it's about to send The same, you know, it wants to update both copies, right?

[40:19] It keeps them in sync. It's about to send this put, but just before it sends the put to the second server, it crashes. power failure, bug in operating system or something. So now the state we're left in, sadly, is that we sent this put and so we've updated one of the two replicas to have value 21, but the other one's still with 20. Now somebody comes along and reads with a "get" And they might get... They want to... Read the value associated with key one, they might get 21 or they might get 20, depending on who they talk to. And even if the rule is you always talk to the top server first, If you're building a fault tolerance system, the actual rule has to be Oh, you talk to the top server first, unless it's failed, in which case you talk to the bottom server.

[41:00] Um, So either way, someday you risk exposing this stale copy of the data. to some future get. It could be that many gets get the updated 21 and then Like next week, all of a sudden, some get yields, you know, a week old copy of the data. So that's not very consistent. Right? in order, but you know, it's, the kind of thing that could happen. Right? and we're not careful. We need to actually write down what the rules are going to be about puts and gets given this danger of due to replication.

[41:37] And it turns out there's many different the definitions you can have of consistency. Um, Many of them are relatively straightforward. Many of them sound like, well, I get yields the you know, value put by the most recently completed put. All right. And so that's usually called strong consistency. It turns out also it's very useful to build systems that have much weaker consistency. That for example, do not guarantee anything like I get it.

[42:11] sees the value written by the most recent put. And the reason, so there's strongly consistent systems - - They usually have some version of get seeing most recent puts. I think you have to... There's a lot of details to work out. There's also weakly consistent, many sort of flavors of weakly consistent systems that do not make any such guarantee. on that. and it may guarantee you well you know, if, someone does a put, then you may not see the put. You may see old values that weren't updated by the put for an unbattered amount of time maybe.

[42:47] Um, And the reason for-- people being very interested in weak consistency schemes. is that Strong consistency, that is, having RIS actually see, be guaranteed to see the most recent right. That's a very expensive spec to implement. um because what it means is almost certainly that you have to, somebody has to do a lot of communication in order to, actually implement. some notion of strong consistency. If you have multiple copies, Um, It means that either the writer or the reader, or maybe both, has to consult every copy. Like in this case, um where maybe a client crashed, left one updated, but not the other.

[43:29] If we wanted to implement strong consistency in maybe a simple way in this system, we'd have readers read both of the copies or if there's more than one copy, all the copies. and use the most recently written value that they find. Um. but that's expensive. That's a lot of chit chat. to read one value. So in order to avoid communication as much as possible, Um. particularly if replicas are far away, people build weak systems that might actually allow the stale read of an old value in this case.

[44:01] Um, although there's often more semantics attached to that to try to make these weak schemes And where this communication problem, you know, strong consistency. requiring expensive communication. Where this really runs you into trouble is that If we're using replication for fault tolerance, then We really want the replicas to have independent failure probability, to have uncorrelated failure. So, for example, putting both of the replicas of our data in the same rack, in the same machine room, is probably a really bad idea.

[44:38] because if someone trips over the power cable to that rack, both of our copies of our data are gonna die. Because they're both attached to the same power cable on the same rack. Um, So in the search for making replicas as independent in failure as possible in order to get decent fault tolerance, People would love to put different replicas as as far apart as possible, like in different cities. or maybe on opposite sides of the continent. So an earthquake that destroys one data center will be extremely unlikely to also destroy The other data center that has the other copy.

[45:13] Um, You know, so we'd love to be able to do that. If you do that, then the other copy is thousands of miles away, And the rate at which light travels means that it may take on the order of milliseconds or tens of milliseconds to communicate to a data center across the continent in order to update the other copy of the data. And so that makes this The communication required for strong consistency, for good consistency, potentially extremely expensive. Like every time you want to do one of these put operations, or maybe a get, depending on how you implement it, You might have to sit there waiting for like 10 or 20 or 30 milliseconds in order to talk to both copies of the data to ensure that they're both updated or both checked.

[45:57] to find the latest copy. Um, And That tremendous expense, right? This is 10 or 20 or 30 milliseconds on machines that, after all, will execute like a billion instructions per second. So we're wasting a lot of potential instructions while we wait. People often build much weaker systems. You're allowed to only update the nearest copy or only consult the nearest copy. Now, I mean, there's a huge sort of amount of academic and real world. research on had us. structure weak consistency guarantee so they're actually useful to applications and how to take advantage of them in order to actually get high performance.

[46:35] Thank you. All right, so that's a lightning preview of the... technical ideas in the course. Any questions about this? before I start talking about MapReduce. All right, I want to switch to MapReduce. That's a sort of detailed case study that's actually going to illustrate most of the ideas. that we've been talking about here. And that produces a system that was Uh...

[47:06] originally designed and built and used by Google, I think the paper dates back to 2004. The problem they were faced with was that they were running huge computations on terabytes and terabytes of data. creating an index of all of the content of the web or analyzing the link structure of the entire web in order to identify the most important pages or the most authoritative pages.

[47:36] And so, you know, the whole web is-- was even in those days tens of terabytes of data. Um... Building an index of the web is basically equivalent to a sort running sort of the entire data. Sort, you know, it's like... reasonably expensive. and to run a sort on the entire content of the web on a single computer I don't know how long it would have taken, but you know, weeks or months or years or something. So, Google at the time was desperate to be able to run giant computations on giant data on thousands of computers.

[48:09] in order that the computations could finish rapidly. It was worth it to them to buy lots of computers so that their engineers wouldn't have to spend a lot of time reading the newspaper or something waiting for their big compute jobs to finish. Um... And so for a while, they had their clever engineers sort of hand write, you know, if you needed to write a web indexer or some sort of link, web link analysis tool. you know, Google bought the computers and they say, "Here, engineers, you know, do--run whatever software you like on these computers."

[48:40] they would laboriously write the sort of one-off manually written software to take whatever problem they were working on and sort of somehow farm it out to a lot of computers and organize that computation and get the data back. Um, If you only hire engineers who are skilled distributed systems experts, Maybe that's OK, although even then, it's probably very wasteful of engineering effort. But they wanted to hire people who were skilled at something else. Um, And not necessarily...

[49:13] Um... engineers who wanted to spend all their time writing distributed system software. So they really needed some kind of framework that would make it easy to just, have their engineers Right? the kind of guts of whatever analysis they wanted to do, like sort algorithm or web index or link analyzer or whatever. Just write the guts of that application and not run, be able to run it on a thousands of computers. um without worrying about the details of how to spread the work over the thousands of computers, how to organize whatever data movement was required, how to cope with the inevitable failures.

[49:49] So they were looking for a framework that would make it easy for non-specialists to be able to write and run giant distributed computations. Um, And so that's what MapReduce is all about. Amen. And the idea is that the programmer just write the application designer, consumer of this distributed computation and just be able to write a simple map function and a simple reduce function, Good. don't know anything about distribution. and the MapReduce framework would take care of everything else.

[50:23] Um, So an abstract view of what MapReduce is up to is It starts by assuming that there's some input and the input is split up into some a whole bunch of different files or chunks in some way. We're imagining that You know, We have input file one, input file two, input file three, Etc. You know, and these inputs are maybe Help.

[50:53] web pages crawled from the web or more likely sort of big files that contain many web--each of which contains many web files. crawl from the web. All right, and the way MapReduce starts is that you define a map function and the MapReduce framework is going to run your map function on each of the input files. you Thank you. And of course you can see here there's some obvious parallelism available.

[51:25] can run the maps in parallel. So each of these map functions only looks at its input and produces output. The output that a map function is required to produce is a list. Takes a file as input and a file as some fraction of the input data, and it produces a list of key value pairs as output. the map function. And so, for example, let's suppose we're writing the simplest possible MapReduce example, a word count MapReduce. job, who's is The goal is to count the number of occurrences of each word.

[51:59] So your map function might emit key value pairs where the key is the word, and the value is just one. So for every word it sees, so this map function will split the input up into words. For every word it sees, it emits that word as the key and one as the value. And then later on we'll count up all those ones. in order to get the final output. Input one has the word. A in it. and the word B in it. And so the output the map is going to produce is Key A value 1, key B value 1.

[52:32] Maybe the second map indication sees a file that has a a b in it and nothing else so it's going to implement output B1, Maybe this third input has an A in it. and a C in it. All right, so we run all these maps on all the input files. And we get this intermediate, what the paper calls intermediate output. which is for every map, a set of key value pairs as output. Then the second stage of the computation is to run the reduces.

[53:04] Thank you. Um, And the idea is that the MapReduce framework collects together all instances from all maps of each keyword. So the MapReduce framework is going to collect together all of the A's you know, from every map, every key value pair whose key was A, it's gonna take Collect them all. and hand them to *knocking* one call of the programmer-defined reduce function. And then it's going to take all the bees and collect them together. Of course, it requires real collection because they were different instances of Key B were produced by different indications of map on different computers. So we're not talking about data movement.

[53:50] So we're going to collect all the B keys and hand them to a different call to reduce that's has all of the B keys. as its arguments, and same with C, all the C's. So this is gonna be the MapReduce framework will arrange for one call to reduce for every key that occurred in Amen. any of the map output. Um, And for our sort of silly word count, example all these reduces have to do or any one of them has to do is just count the number of items passed to it. It doesn't even have to look at the items because it knows that each of them is--the word is responsible for plus one as the value. You don't have to look at those ones, we just count them. So this reduce is gonna produce Um, A and then the count.

[54:43] Of its inputs, this reduce. It's gonna produce the key associated with it and then count of its values, which is also two, Thank you. Thank you. Thank you. So this is what a typical... MapReduce job looks like. the high level. Just for completeness, the--I'm sorry. Well, a little bit of terminology. The whole computation is called the job. any one invocation of map or reduce is called a task. So we have an entire job and it's made up of a bunch of map tasks.

[55:21] and then a bunch of reduced tasks. Um... So an example for this word count, you know, what the map and reduce functions would look like. Thank you. Thank you. Um... Thank you. Thank you. The map function takes a key and a value as arguments. And now we're talking about functions like written in an ordinary programming language like, C++ or Java or who knows what.

[55:52] um So this is just code ordinary people can write. What a map function for word count would do is split the key is the file name, which typically is ignored, we don't really care what the file name was. And the V is the content of "this maps input file." So V just contains all this text. We're going to split V into words. Thank you. Thank you. And then for each word, Thank you.

[56:24] *knocking* *knocking* *knocking* We're just gonna emit. And emit takes two arguments. MIT's call only map can make, and MIT is provided by the MapReduce framework. We get to produce, we hand a MIT a key, which is the word... and a value which is Bye. string one. So that's it for the map function. A word count map function in MapReduce literally could be this simple.

[56:56] Um, So. their sort of promise to make the And, you know, this map function doesn't know anything about distribution or multiple computers the fact we need to move data across the network, or who knows what. This is extremely... straightforward. And the reduce function for... word count um The reduce is called with Remember each reduce is called with sort of all the instances of a given key on the MapReduce framework calls reduce with a the key that it's responsible for and a vector of all the values that the maps produced.

[57:35] associated with that key. The key is the word, the values are all ones, we don't really care about them, we only care about how many there were um And so, reduce has its own emit function that just takes a a value to be emitted as the final output. as the value for the This key. So we're going to admit the length. Thank you. of this array. Thank you. So this is also about as simple as reduced functions are. in MapReduce, namely, Extremely simple.

[58:08] and requiring no knowledge about fault tolerance or Anything else? All right, any questions about... The basic framework, yes. and not... necessary but this might return something. I'm at it. Like France, France, France. using the MapReduce framework that maybe it's reduce with access. that step some number of times. You mean can you feed the output of the reduces sort of-- Yeah.

[58:43] Thank you. Oh, yes. Oh yes, in real life, all right. In real life, it is routine among MapReduce users to you know, define a MapReduce job that took some inputs and produced some outputs and then have a second MapReduce job, you know, if you're doing some very complicated multi-stage analysis. or iterative algorithm. like PageRank, for example, which is the algorithm Google uses to sort of, Estimate how important or influential different web pages are. That's an iterative algorithm is sort of gradually converges on an answer. And if you implement a MapReduce, which I think they originally did, You have to run the MapReduce job multiple times.

[59:28] The output of each one is sort of-- you know, list of web pages, with an updated sort of value or weight or importance for each web page. So it was routine to take this output and then use it as the input to another MapReduce job. We can't do it forever. Oh yeah. it is. all the tears "Well, yeah, you need to sort of set things up the output, you need to-- the reduced function sort of in the knowledge though.

[1:00:00] Meet the produce. data that's in the format or has the information required for the next MapReduce job. I mean, this actually brings up a little bit of a shortcoming in the MapReduce. framework, which is, it's great. if you're Thank you. if the algorithm you need to run is easily expressible as a map followed by this sort of "shuffling of the data by key, followed by a reduce, "and that's it." MapReduce is fantastic for algorithms that can be cast in that form.

[1:00:30] And furthermore, each of the maps has to be completely independent. required to be uh... functional, pure functional functions that just look at their arguments and nothing else. And you know, that's like, it's a restriction. And it turns out that many people want to run much longer pipelines that involve lots and lots of different kinds of processing. And with MapReduce, you have to sort of cobble that together from multiple--and MapReduce. distinct map-produced jobs. and more advanced systems, which we will talk about later in the course, are much better at allowing you to specify the complete pipeline of computations, and they'll do optimization.

[1:01:09] the framework realizes all the stuff you have to do. organize much more complicated efficiently. optimize, much more complicated. Computation. Your question. So in the paper, they distinguish between mappers and map functions. I guess that's the-- like the processes that are running the map. What are the... and welcome the processes that are-- From the programmer's point of view, it's just about map and reduce.

[1:01:43] From our point of view, it's gonna be about the worker processes. and the worker servers that that are part of MapReduce framework, among many other things. call them out from produce functions. So-- um Yeah, from our point of view, we care a lot about how this is organized by the surrounding framework. This is sort of the programmers view with all the distributed stuff stripped out. Um. Yes? Thank you. Sorry, I got to...

[1:02:21] Say it again. Sorry, do you emit locally? Oh, you mean where does the emit data go? Thank you. Okay, so there's two questions. One is... When you call emit, what happens to the data? and the other is where the functions run. So, Thank you. Um. The actual answer is that First, where does the stuff run? There's a number of, say, a thousand servers. Actually, the right thing to look at here is figure one in the paper.

[1:02:59] Um, Though sitting underneath this in the real world, there's some big collection of servers. And Um. We'll call them maybe worker servers or workers. And. There's also a single master server that's organizing the whole computation. And what's going on here is the master server knows that there's some number of input files, you know, 5,000 input files. and it farms out invocations of map to the different workers. So it'll send a message to worker seven saying, please run this map function on such and such an input file.

[1:03:39] And then the worker function which is, you know, part of MapReduce and knows all about MapReduce, well then, Um, Read the file, read the input, whatever, whichever input file. and call this map function with the file name value as arguments. than that worker process. will is what implements emit. And every time the map calls emit, The worker process. will write this data to files on the local disk.

[1:04:11] So what happens to map emits? is they produce files on the map worker's local disk that are accumulating all the keys and values produced by the mapped run on that worker. um So at the end of the math phase, What we're left with is all those worker machines Each of which has the output of some of whatever maps were run on that worker machine. Then the MapReduce workers arrange to move the data to where it's going to be needed for the reduces and since I And a typical big computation This reduced syndication is gonna need all map output that mentioned the key A, but it's gonna turn out, you know, this is a sort of simple example, but probably, In general, every single map invocation will produce lots of keys, including some instances of key A.

[1:05:13] So typically in order, before we can even run this reduce function, the MapReduce framework that is the MapReduce worker running on one of our thousand servers, is going to have to go talk to every single other of the thousand servers and say, "Look, I'm gonna run the reduce for key A, please. Look at the intermediate map output stored in your disk and fish out all of the instances of key A and send them over the network to me. So the reduced worker is going to do that. It's going to fetch from every worker.

[1:05:44] all of the instances of the key that it's responsible for, that the master has told it to be responsible for. And once it's collected all of that data, then it can call reduce. And the reduce function itself calls reduce emit, which is different from the map in it. What reduces emit does is writes the output to A file. in a cluster file service that Google uses. So here's something I haven't mentioned.

[1:06:15] Um, I haven't mentioned where the input lives. and where the output lives. They're both vials. Um, because any piece of input We want the flexibility to be able to read any piece of input on any worker server. That means we need some kind of network file system to store the input data. Um, And so indeed, the paper talks about this thing called GFS, for Google File System.

[1:06:48] Um, And GFS is a cluster file system. And GFS actually runs on exactly the same set of workers worker servers that run MapReduce. And the input GFS just automatically, when you, you know, it's a file system, you can read and write files. it just automatically splits up any big file you store on it. across lots of servers in 64 megabyte chunks. So if you write, if you have 10 terabytes of crawled web page contents. and you just write them to GFS, even as a single big file, GFS will automatically split that vast amount of data up into 64 kilobyte chunks distributed evenly over all of the GFS servers, which is to say, all the servers that Google has available.

[1:07:32] And that's fantastic, that's just what we need. If we then want to run a MapReduce job that takes the entire crawled web as input. the data's already stored in a way that's split up evenly across all the servers. And so that means that um the map workers, you know, we're going to launch If we have a thousand servers, we're going to launch a thousand map workers each reading one one thousandth of the input data. and they're gonna be able to read the data in parallel from a thousand GFS file servers.

[1:08:02] That's getting... A tremendous total. read throughput. you know, the read-through bit of a thousand servers. Yeah. Thank you. running the map. So are you thinking maybe that Google has one set of physical machines that run GFS and a separate set of physical machines that run MapReduce jobs. saying that the May I have two?

[1:08:37] Okay. They're not necessarily . - Right, so the question is, what is this arrow here? actually involve. Um, And the answer to that actually sort of changed over the years as Google's of all of this system. You know, with this in the most general case, if we have big files stored in some big network file system. Like, you know, it's like GFS is a bit like AFS. you might have used on Athena. where you go talk to some collection, your data's split over, big collection of servers, you have to go talk to those servers over the network to retrieve your data.

[1:09:13] Um, In that case, what this arrow might represent is Thank you. the map, the MapReduce worker process has to go off and talk across the network to the correct GFS server or maybe servers. that store its part of the input. and fetch it over the network to the-- MapReduce worker machine in order to pass the map. And that's certainly the most general case. And that was eventually how MapReduce actually worked. In the world of this paper though, And if you did that, that's a lot of network communication.

[1:09:47] You're talking about 10 terabytes of data, and then we have to move 10 terabytes across their data center network, which... you know, data center networks run at gigabits per second, but it's still a lot of time to move. tens of terabytes of data. Thank you. in order to try to, and indeed in the world of this paper in 2004, The most constraining bottleneck in their MapReduce system was network throughput. because they were running on a network, if you read as far as the evaluation section. their network, their network was Um...

[1:10:23] They had thousands of machines, whatever, and they would collect machines, they would plug machines into, you know, each rack of machines into, you know, an Ethernet switch for that rack or something. But then, you know, they all need to talk to each other. But there was a root Ethernet switch. that all of the rack Ethernet switches talk to. And this, and you know, so if you just pick some MapReduce worker and some GFS server chances are at least half the time, the communication between them has to pass through this one root switch. Their root switch had only some amount of total throughput, which I forget, uh... you know some number of gigabits per second.

[1:11:07] um Anyway, I forget the number, but when I did the division, that is divided up the total throughput available in the root switch by the roughly 2,000 servers that they used in the paper's experiments. What I got was that each machine's share of the root switch, or of the total network capacity, was only 50 megabits per second. in their setup. Subtitles by the Amara.org community So 50 megabits per second per machine.

[1:11:39] And that might seem like a lot, 50 megabits, gosh, millions and millions. But it's actually quite small compared to how fast, say, disks run or CPUs run. And so this, with their network, this 50 megabits per second was like a tremendous limit. They really stood on their heads in the design described in the paper to avoid using the network. And they played a bunch of tricks to avoid sending stuff over the network when they possibly could avoid it. One of them was They ran the GFS.

[1:12:12] servers. and the MapReduce workers on the same set of machines. so that they have a thousand machines They'd Run GFS, they implement their GFS service on that thousand machines and run MapReduce on the same thousand machines. And then when the master was splitting up the map work and sort of farming it out to different workers, it would cleverly when it was I'M GOING TO GO TO THE NEXT QUESTION. about to run the map. that was gonna read from input file one, it would figure out from GFS which server actually holds input file one on its local disk.

[1:12:50] And it would-- Send the map. for that input file to the MapReduce software on the same machine. so that by default, this arrow is actually local read from the local disk and did not involve the network. And you know, depending on failures or load or whatever, that it couldn't always do that. But almost all of the maps would be run on the very same machine that stored the data, thus saving them um vast amount of time that they would otherwise have had to wait to move the input data across the network.

[1:13:21] Um, The next trick they played is that map, as I mentioned before, stores its output on the local disk of the machine that you run the map on. So, again, storing the output of the map does not require network communication, at least because the output's stored on the disk. however We know for sure that one way or another, in order to group together all of the way the MapReduce is defined, In order to group together all of the values associated with the given key and pass them single invocation to produce on some machine, this is going to require network communication.

[1:13:59] We're going to--you know, we want to--we need to--we're That's all the A's and give them a single machine to have to be moved across the network. And so this shuffle, this movement of the keys from this kind of, you know, originally stored by Rowe on the same machine that ran the map. We need them essentially to be stored on by column on the machine that's going to be responsible for reduce. This transformation of row storage to essentially column storage is called, the paper calls a shuffle. And it really that required moving every piece of data.

[1:14:30] across the network. from the math that produced it to the reduce that we needed. And that was like the expensive part of the... Um. of the MapReduce. Yeah. Why didn't they? make the something that would run sort of like you would have you Keep your... as you have it already. pick one of the then you would have waited all night. You're right, you can imagine a different definition in which you have a more kind of streaming reduce. I don't know I haven't thought this through. I don't know why. whether that would be feasible or not. Certainly as far as programmer interface, like if the goal, their number one goal really, to be able to make it easy to program.

[1:15:11] by people who just had no idea what was going on in the system. So it may be that this spec, this is really the way reduce functions look. in C++ or something. Like a streaming version of this is now starting to look I don't know how it looked. Probably not this simple. But you know, maybe it could be done that way. And indeed, many modern systems People have gotten a lot more sophisticated. with modern things that are the successors of MapReduce. And they do indeed involve processing streams of data often rather than this very batch approach. It is a batch approach in the sense that we wait until we get all the data and then we process it.

[1:15:55] So first of all, you then have to have a notion of finite inputs, right? And modern systems often do indeed use streams. and... are able to take advantage of some efficiencies due to that. Thank you. but not MapReduce. Thank you. Um... Okay, so this is the point at which the shuffle is where all the network traffic happens, this can actually be a vast amount of data. So if you think about sort, If you're sorting, the output of the sort has the same size as the input to the sort. So that means that if your input is 10 terabytes of data, and you're running a sort, you're moving 10 terabytes of data across the network at this point.

[1:16:37] And your output will also be 10 terabytes and so this is-- quite a lot of data and indeed it is for many map-produced jobs, although not all. There significantly reduce the amount of data at these stages. I'm... Somebody mentioned, oh, what if you want to feed the output of reduce into another MapReduce And indeed, that was often what people wanted to do. And in any case, the output of the reduce might be enormous, like for sort or web-in-mixing. the output that it produces is on 10 terabytes of input. the output of the reduce is again gonna be 10 terabytes. So the output of the reduce was also stored on GFS.

[1:17:10] And the system would-- you know, reduce would just produce these key value pairs, but the, Thank you. MapReduce framework would gather them up and write them into giant files on GFS. Um, And so there was another, round of network communication required to get the output of each reduce to the GFS server needed to store that produce. You might think that they could have... Played the same trick with the output of storing the output on the GFS server that happened to run um the MapReduce worker that ran the reduce.

[1:17:48] And maybe they did do that, but because GFS as well as splitting data for performance, also keeps two or three copies for fault tolerance. That means no matter what, you need to write one copy of the data across a network to a different server. So there's a lot of network communication here, and a bunch here also. Um, And it was this network communication that really limited the... Thruppidimapidus. in 2004. Um, In 2020, Because this network arrangement was such a limiting factor for so many things people wanted to do in data centers.

[1:18:22] Modern data center networks are a lot faster at the root than this was. Um, One typical data center network you might see today actually has many root, instead of a single root switch that everything has to go through, you might have-- many root switches and each rack switch as a connection to each of these sort of replicated root switches and the traffic is split up. among the root switches. So modern data center networks have far more network throughput um And because of that, actually, modern-- I think Google sort of stopped using Macrodeuce a few years ago, but Um, before they stopped using it.

[1:19:01] The modern MapReduce actually no longer try to run the maps. on the same machine as the data was stored on. They were happy to load the data from anywhere because they just assumed the network It was extremely fast. Okay. We're out of time for MapReduce. We have a lab. at the end of next week in which you'll write your own somewhat simplified MapReduce. So, Have fun with that. and see you on Thursday.

在Vidleaf工作台中打开

搜索转录文本,选择行,复制带时间戳的引文,翻译。

在工作台中打开 →

署名

MIT 6.824 的“讲座 1:导论”:分布式系统(https://www.youtube.com/@6.824),依据 CC BY 3.0 许可(https://creativecommons.org/licenses/by/3.0/)。源视频:https://www.youtube.com/watch?v=cQP8WApzIQQ。本页是视频的文字转录稿,添加了段落分隔和时间戳;创作者与 Vidleaf 无关联,也不为其背书。Vidleaf 添加了 AI 标点和 AI 生成的摘要;原始措辞仍可在本页查看。

您是创作者或权利持有人吗?请求更正或移除:copyright@vidleaf.app(参见关于这些页面)。

最后更新于