并行系统 Parallelism System(一)

67 阅读6分钟

并行系统 Parallelism System(一)

RPC(Remote Procedure Call):远程过程调用

q1:什么是分布式系统? What is a Distributed System?

  1. 一个分布式系统是由多台独立的计算机组成的系统,这些计算机通过网络互相连接,并且它们协同工作,共同完成一个任务,就像它们是单一的、统一的系统一样

q2:为什么我们需要分布式系统? Why do we need Distributed Systems?

  1. 可伸缩性 (Scalability):

    1. 服务用户量增长时,一台服务器可能无法处理所有的请求
    2. 分布式系统可以通过增加更多的机器来线性地提升处理能力
  2. 可用性/容错性 (Availability/Fault Tolerance):

    1. 单点故障:如果你的服务只运行在一台机器上,那台机器一旦发生故障(硬件损坏、软件崩溃、断电等),整个服务就瘫痪了
    2. 分布式系统可以通过在多台机器上部署相同的服务来避免单点故障。即使其中一台机器出现问题,其他的机器仍然可以继续提供服务
  3. 地理分布 (Geographical Distribution):

    1. 用户可能分布在全球各地。将数据和服务放在离用户更近的地方,可以减少网络延迟,提高用户体验
    2. 将网站的静态资源(图片、视频)缓存在全球各地的服务器上,用户访问时从最近的服务器获取
  4. 资源共享 (Resource Sharing):

    1. 分布式系统中,可以共享昂贵的硬件资源(如高性能计算集群)或软件资源(如数据库服务)
    2. 云计算平台,多个用户共享同一批服务器资源
  5. 透明性 (Transparency):

    1. 虽然系统内部很复杂,但对用户来说,它应该看起来很简单,就像使用一台普通的计算机一样
    2. 用户不需要关心数据存储在哪里,哪个服务器正在处理他们的请求

  1. 并发性 (Concurrency): 多台机器同时执行操作
  2. 故障独立性 (Independent Failures): 组成系统的一些部分可能会独立于其他部分失效
  3. 网络问题 (Network Issues): 网络可能不可靠、有延迟或分区
  4. 一致性 (Consistency): 多个副本的数据如何保持一致
  5. 异构性 (Heterogeneity): 系统中可能包含不同硬件、操作系统和编程语言的机器

MapReduce

Map:

  1. 用于转换数据

Reduce:

  1. 聚合数据

MapReduce编程模型:核心抽象

  1. Map函数由用户编写,是数据处理的第一步,接收一个输入键/值对(k1, v1);
  2. Map函数的核心作用是处理这个输入对,并生成一组中间键/值对 list(k2, v2)
  3. 中间键/值对是Map和Reduce阶段之间沟通的桥梁,它们将被MapReduce库收集、分组并传递给Reduce函数

Map与Reduce的协同工作机制

  1. Map函数将原始数据转换为中间键/值对
  2. MapReduce库负责按键对这些中间对进行分组和排序
  3. 将每个唯一的中间键及其所有关联值传递给Reduce函数进行最终聚合

eg:词频统计

场景:

  1. q1:现在是Google,手头有海量的网页文档,你想要统计出每个单词在所有文档中出现的总次数。
  2. q2:如果只有几百个文档,你可能自己写个脚本就能搞定。但现在是数以亿计的文档,总大小达到数TB甚至PB级别,一台机器根本处理不过来。

挑战:

  1. 数据量巨大: 单机无法存储和处理
  2. 并行化复杂: 如何把任务分给几千台机器?
  3. 故障处理: 这么多机器,总有会出故障的,怎么保证计算不中断、结果不错?
  4. 数据传输: 机器之间的数据交换量巨大,如何高效传输?

MapReduce为解决该问题,将复杂的分布式计算抽象为两个核心阶段:

  1. Map(映射);2. Reduce(归纳)

MapReduce的分而治之:Map阶段

Map阶段是数据处理的起点,它负责将原始的、大规模的输入数据分解成更小的、可独立处理的中间键值对

  1. 输入: MapReduce系统会将海量文档自动分割成许多小块(例如,每块64MB),并将这些小块分发给集群中的不同机器(称为“Map Worker”)

  2. Map函数:

    1. 每个Map Worker会接收到分配给它的一篇或多篇文档
    2. Map函数的工作就是:读取文档内容,每遇到一个单词,就发出一个 (单词, "1") 的键值对。 这里的 "1" 表示该单词出现了一次
    3. map (文档名称 key, 文档内容 value):
        for each word w in value:
          EmitIntermediate (w, "1"); // 发出 (单词, "1")
      
  3. 执行示例:

    1. Map Worker 1 处理文档A:

      1. The" -> ("The", "1") "quick" -> ("quick", "1") "brown" -> ("brown", "1") "fox" -> ("fox", "1") "jumps" -> ("jumps", "1") "over" -> ("over", "1") "the" -> ("the", "1") "lazy" -> ("lazy", "1") "dog" -> ("dog", "1")
    2. Map Worker 2 处理文档B:

      1. "Fox" -> ("Fox", "1")

        "is" -> ("is", "1")

        "quick" -> ("quick", "1")

        "and" -> ("and", "1")

        "lazy" -> ("lazy", "1")

  4. Map阶段的中间结果:

    1. 每个Map Worker都在自己的本地磁盘上生成了大量的 (单词, "1") 键值对
    2. 这些键值对是无序的,并且同一个单词可能在不同的Map Worker上都出现了
MapReduce的“合而治之”:Shuffle & Reduce阶段

Map阶段结束后,MapReduce框架会接管,执行一个关键的Shuffle(混洗)和Sort(排序) 阶段,然后才进入Reduce阶段。

  1. Shuffle(数据混洗与分组):

    1. MapReduce系统会收集所有Map Worker生成的中间键值对
    2. 它会根据单词(中间键)进行分区,确保所有相同的单词都被发送到同一个Reduce Worker
    3. 例如,所有关于 "quick" 的 ("quick", "1") 都会被发送到同一个Reduce Worker
    4. 容错体现: 如果某个Map Worker在传输数据时失败了,Master会重新调度这个Map任务,让另一个Worker重新生成数据并发送给Reduce Worker,确保数据不丢失
  2. Sort(排序):

    1. 当Reduce Worker接收到所有分配给它的中间键值对后,它会根据键(单词)对这些数据进行排序。这样,所有相同的单词及其对应的 "1" 就会紧挨着排列

    2. eg:

      1. ("fox", "1") (来自文档A)

        ("Fox", "1") (来自文档B)

        ("lazy", "1") (来自文档A)

        ("lazy", "1") (来自文档B)

        ("quick", "1") (来自文档A)

        ("quick", "1") (来自文档B)

    3. Combiner优化:

      1. MapReduce还允许指定一个Combiner函数
      2. 函数在Map Worker本地运行,对本地的中间结果进行“预聚合”
      3. 例如,在Map Worker 1上,它可能会把 ("the", "1")("the", "1") 先聚合成 ("the", "2"),这样就减少了通过网络传输的数据量
    4. Reduce函数(编写的逻辑)

      1. 每个Reduce Worker会接收到一个单词(键)和与该单词相关联的所有 "1" 的列表
      2. Reduce函数的工作就是:遍历这个列表,将所有的 "1" 相加,得到该单词的总计数,然后发出最终的 (单词, 总计数) 键值对
    5. 实际执行示例(Reduce Worker 1):

      1. 接收到 ("fox", ["1", "1"]) -> total_count = 1 + 1 = 2 -> 发出 ("fox", "2")

        接收到 ("lazy", ["1", "1"]) -> total_count = 1 + 1 = 2 -> 发出 ("lazy", "2")

        接收到 ("quick", ["1", "1"]) -> total_count = 1 + 1 = 2 -> 发出 ("quick", "2")

        ...

      2. Reduce阶段的最终结果: 每个Reduce Worker会将自己处理的最终结果写入一个独立的输出文件(通常存储在分布式文件系统,如GFS中)