第三部分派生数据

我们将讨论如何将多个不同数据系统整合至一致的应用程序体系结构中。

记录系统与派生数据系统

存储与处理数据的系统按照高层次分类可以分为两大类:

  • 记录系统:一个记录系统也被称为真实数据系统,拥有数据的权威版本。
  • 派生数据系统:JK生数据系统中的数据则是从另一个系统中获取已有数据并以某种方式进行转换或处理的结果。如果派生数据丢失,用户可以从原始数据源进行重建。
第十章批处理系统

三种不同类型的系统:

  • 在线服务(或称在线系统):服务等待客户请求或指令的到达。
  • 批处理系统(或称离线系统):批处理系统接收大量的输入数据,运行一个作业来处理数据,井产生输出数据。
  • 流处理系统(或称近实时系统):流处理介于在线与离线/批处理之间,流式作业在事件发生后不久即可对事件进行处理

批处理是构建可靠、可扩展与可维护应用的重要组成部分。

使用UNIX工具进行批处理

简单日志分析

使用UNIX的shell组合,可以在几分钟内完成许多数据分析任务

命令链与自定义程序

Ruby程序并不像UNIX管道那样简沽,但是它的可读性很强,除了表面上的语战差异之外,执行流程也存在很大差异。如果在大文件上运行此分析,差异会变得更加明显。

排序与内存中聚合

Ruby脚本需要一个内存哈希表进行排序,如果数据比较小,可以在内存中进行操作,而如果作业的工作集大于可用内存,则需要使用磁盘。归并排序在磁盘上有良好的顺序访问模式。
GNUCoreutils(Linux)中的sort实用程序通过自动唤出到磁盘的方式支持处理大于内存的数据集,且排序可以自动井行化以充分利用多核CPU

UNIX设计哲学

  • 每个程序做好一件事。
  • 期待每个程序的输出成为另一个尚未确定的程序的输入。
  • 尽早尝试设计和构建软件,甚至是操作系统,最好在几周内完成。
  • 优先使用工具来减轻编程任务。

统一接口

如果希望某个程序的输出成为另一个程序的输入,也就意味着这些程序必须使用相同的数据格式。
在UNIX中,这个接口就是文件(更准确地说,是文件描述符),文件只是一个有序的字节序列。
尽管经过几十年的发展依然不够完美,但UNIX统一接口的表现仍然称得上卓越。不过,并没有太多软件能像UNIX工具一样实现交互操作与组合

逻辑与布线分离

UNIX工具的另一个特点是使用标准输入(stdin)和标准输出(stdout)。
但是,使用stdin和stdout也有其局限性。需要多个输入或输出的程序会变得很棘手。用户不能将程序的输出传输给一个网络连接

透明与测试

UNIX工具如此成功的部分原因在于,它可以非常轻松地观察事情的进展。
然而,UNIX工具的最大局限在于它们只能在一台机器上运行

MapReduce与分布式文件系统

MapReduce有点像分布在数千台机器上的UNIX工具。
MapReduce作业通常不会修改输入,除了生成输出外没有任何副作用。
MapReduce作业在分布式文件系统上读写文件
HDFS基于无共享原则,无共享方法不需要特殊硬件,只需要通过传统数据中心网络连接的计算机。
HDFS创建了一个庞大的文件系统,来充分利用每个守护进程机器上的磁盘资源。考虑到机器和磁盘的容错,文件块被复制到多台机器上。
HDFS具有很好的扩展性

MapReduce作业执行

要创建MapReduc巳作业,需要实现两个回调函数,即mapper和reducer
Mapper:每个输入记录都会调用一次mapper程序,其任务是从输入记录中提取关键字和值。
Reducer:MapReduce框架使用由mapper生成的键值对,收集属于同一个关键字的所有值,并使用迭代器调用reducer以使用该值的集合。

MapReduce的分布式执行

MapReduce与UNIX命令管道的主要区别在于它可以跨多台机器并行执行计算,其不必编写代码来指示如何井行化。
mapper和reducer通常是用传统编程语言实现的函数。
MapReduce框架首先要复制代码,然后启动map任务并开始读取输入文件,每次将一条记录传递给回调函数mapper。mapper的输出由键值对组成。
Reduce任务中的计算也被分割成块。Map任务的数量由输入文件块的数量决定,而reduce任务的数量则是由作业的作者来配置的
为了确保具有相同关键字的所有键值对都在相同的reducer任务中处理,框架使用关键字的哈希值来确定哪个reduce任务接收特定的键值对

MapReduce工作流

将MapReduce作业链接到工作流中是非常普遍的,这样,作业的输出将成为下一个作业的输入。

Reduce端的join与分组

MapReduc巳没有索引的概念,至少不是通常意义上的索引。
当给定一组文件作为MapReduce输入时,它读取所有文件的全部内容;数据库将其称作全表扫描。

示例:分析用户事件

join的最简单实现是逐个遍历活动事件,并在(远程服务器上的)用户数据库中查询每个遇到的用户ID。i衷方案首先是可行的,但性能会非常差:吞吐量将受到数据库服务器的往返时间的限制,本地缓存的有效性将很大程度上取决于数据的分布,并且同时运行的大量并行查询很容易使数据库不堪重负
为了在批处理过程中实现良好的吞吐量,计算必须(尽可能)在一台机器上进行。

排序-合并join

当MapReduce框架通过关键字对mapper输出进行分区,然后对键值对进行排序时,结果是所有活动事件和用户ID相同的用户记录在reducer的输入中彼此相邻。
然后reducer可以很容易地执行真正的join逻辑:为每个用户ID调用一次reducer函数。

将相关数据放在一起

在排序-合并join中,mapper和排序过程确保将执行特定用户IDjoin操作的所有必要数据都放在一起,这样就只需要一次reducer调用。

分组

通过某个关键字对记录进行分组。所有具有相同关键字的记录形成一个组,然后在每个组内执行某种聚合操作。

处理数据倾斜

如果join输入中存在热键,则可以使用算法进行补偿。
Pig中的倾斜join方法首先运行一个抽样作业来确定哪些属于热键。在真正开始执行join时,mapper将任何与热键有关的记录发送到随机选择的若干个reducer中的一个
Crunch中的共享join方住与此类似,但需要明确指定热键,而不是使用抽样作业。
Hive的倾斜join优化采取了另一种方怯。它需要在表格元数据中明确指定热键,井将与这些键相关的记录与其余文件分开存放。

map端join操作

Reduce踹join方惶的优点是不需要对输入数据做任何假设:无论其属性与结构如何,mapper都可以将数据处理好以准备join。然而,不利的一面是,所有这些排序,复制到reducer以及合并educer输入可能会是非常昂贵的操作。
如果可以对输入数据进行某些假设,则可以通过使用所谓的map端join来加快速度

广播哈希join

实现map端join的最简单方住特别适合大数据集与小数据集join,尤其是小数据集能够全部加载到每个mapper的内存中。
另一种方怯并不需要将小数据集加载至内存哈希表中,而是将其保存在本地磁盘上的只读索引中。

分区哈希join

如果以相同方式对map端join的输入进行分区,贝ljO合希join方法可以独立作用于每个分区。
如果分区操作正确完成,就可以确定所有要j0in的记录都位于相同编号的分区中,因此每个mapper只需从每个输入数据集中读取一个分区就足够了。

map端合并join

如果输入数据集不仅以相同的方式进行分区,而且还基于相同的关键字进行了排序,则可以应用map端join的另一种变体。
mapper可以执行通常由reducer执行的合并操作:按关键字升序增量读取两个输入文件,并且匹配具有相同关键字的记录。

具有map端join的MapReduce工作流

当下游作业使用MapReducejoin的输出时,map端或reduce端join的不同选择会影响到输出结构。reduce端join的输出按join关键字进行分区和排序,而map端join的输出按照与大数据集相同的方式进行分区和排序

批处理工作流的输出

批处理即不是事务处理,也不是分析。

生成搜索索引

Google最初使用MapReduce的目的是为其搜索引擎建立索引。
如果需要对一组固定文档进行全文检索,则批处理是构建索引的有效方怯:mapper根据需要对文档集进行分区,每个reducer构建其分区索引,并将索引文件写入分布式文件系统。
由于按关键字查询搜索索引是只读操作,因此这些索引文件一旦创建就是不可变的。如果索引的文档集合发生更改,则可以选择定期重新运行整个索引工作流,并在完成后用新的索引文件批量替换之前的索引文件。

批处理输出键值

批处理的另一个常见用途是构建机器学习系统,如分类器和推荐系统

批处理输出的哲学

MapReduc巳作业的输出处理遵循相同的原理。将输入视为不可变,避免副作用(例如对外部数据库的写入),批处理作业不仅实现了良好的性能,而且更容易维护:

  • 如果在代码中引入了漏洞,输出错误或者损坏,那么可以简单地回读到先前版本,然后重新运行该作业,将再次生成正确的输出
  • 与发生错误即意味着不可挽回的损害相比,易于回攘的特性更有利于快速开发新功能。
  • 如果map或reduce任务失败,MapReduce框架会自动重新安排作业井在同一个输入上再次运行。
  • 相同的文件可用作各种不同作业的输入
  • MapReduce作业将逻辑与连线(配置输入和输出目录)分开,从而可以更好地隔离问题,重用代码

在Hadoop中,通过使用更多结构化的文件格式,可以消除一些低价值的语法转换

对比Hadoop与分布式数据库

大规模井行处理(MPP)数据库专注于在一个机器集群上井行执行SQL查询分析,而MapReduce和分布式文件系统的结合则更像是一个可以运行任意程序的通用操作系统。

存储多样性

数据库要求根据特定的模型(例如,关系或文档)来构造数据,而分布式文件系统中的文件只是字节序列,可以使用任何数据模型和编码来编写。

处理模型的多样性

MPP数据库属于一体化、紧密集成的软件系统,包括磁盘存储布局、查询计划、调度和执行。由于这些组件都可以针对数据库的特定需求进行调整和优化,因此整个系统可以在其设计的查询类型上实现非常好的性能。
MapReduce使工程师能够轻松地在大型数据集上运行自己的代码。

针对频繁故障的设计

在比较MapReduce和MPP数据库肘,设计方法的另外两个不同点是:如何处理故障和如何使用内存和磁盘。
MapReduce被设计为容忍意外任务终止,不是因为硬件特别不可靠,而是因为任意终止进程的灵活性能够更好地利用集群资源。

超越MapReduce

一方面,MapReduce非常强大:可以使用它来处理那些运行在不可靠的多租户系统上、任务频繁终止的超大规模数据,井且仍然可以完成工作(虽然速度很慢)。另一方面,对于某些类型的处理,其他工具则可能要快几个数量级。

中间状态实体化

有些情况下分布式文件系统上的文件只是中间状态:一种将数据从一个作业传递到下一个作业的方式。将这个中间状态写入文件的过程称为实体化(或物化)。
UNIX管道并不完全实现中间状态,而是只使用一个小的内存缓冲区,逐渐将输出流式传输到输入。

  • MapReduce作业只有在前面作业(生成其输入)中的所有任务都完成时才能启动,而通过UNIX管道连接的进程同时启动,输出一旦生成就会被使用。
  • Mapper通常是冗余的:它们只是读取刚刚由reducer写入的同一个文件,并为下一个分区和排序阶段做准备。
  • 将中间状态存储在分布式文件系统中意味着这些文件被复制到多个节点,对于这样的临时数据来说通常是大材小用了。

数据流引擎

为了解决MapReduce的这些问题,开发了用于分布式批处理的新的执行引擎,它们把整个工作流作为一个作业来处理,而不是把它分解成独立的子作业。
它们通过反复调用用户定义的函数来在单个线程上一次处理一条记录。它们通过对输入进行分区来并行工作,井将一个功能的输出复制到网络上,成为另一个功能的输入。
与MapReduce不同,这些功能不需要严格交替map;和reduce的角色,而是以更灵活的方式进行组合。

容错

将中间状态完全实体化到分布式文件系统的一个优点是持久化,这使得在MapReduce中实现容错变得相当容易:如果一个任务失败了,它可以在另一台机器上重新启动,并从文件系统重新读取相同的输入。

关于实体化的讨论

数据流对MapR巳duce的改进是,不需要自己将所有中间状态写入文件系统。

图与迭代处理

许多图算法通过一次遍历一个边,将一个顶点与相邻顶点join起来以便传递某种信息,重复该过程直到满足某种条件为止。
但是这种“重复直到完成”的想法不能用普通的MapReduce来表示,因为它只执行一次数据传递。这种算法通常需要以选代方式实现,这种方陆有效,但是用MapReduce来实现却非常低效,主要是因为MapReduce没有考虑算法的迭代性质:即使与上一次迭代相比,只有图的一小部分发生了改变,它也总是读取整个输入数据集井产生一个全新的输出数据集。

Pregel处理模型

Pregel模型的选代过程中,顶点保存它在内存中的状态,所以函数只需要处理新输入的悄息。如果图的某个部分没有收到发送消息,则不需要做任何工作。

容错

即使底层网络可能会丢弃、重复或任意延迟消息,但Pregel的实现可以保证在后续迭代中消息在目标顶点只会被处理一次。像MapReduce一样,该框架透明地从故障中恢复,以简化Pregel顶层算陆的编程模型。
这种容错方式是通过在迭代结束时定期快照所有顶点的状态来实现的,即将其全部状态写入持久存储。

并行执行

顶点不需要知道它运行在哪台物理机器上。当它发送消息到其他顶点时,只需要将消息发送至一个顶点ID。
因此,图算法往往会有很多跨机器通信的开销,中间状态(节点之间发送的悄息)往往比原始图大。通过网络发送悄息的开销会显著减慢分布式图算法。

高级API和语言

物理操作批处理过程的问题已经或多或少得到了解决,所以问题已经转向其他领域:改进编程模型,提高处理效率,扩大解决的问题域等。

转向声明式查询语言

与编写执行join的代码相比,指定join作为关系运算符的优点在于,框架可以分析join输入的属性,井自动决定哪个join算法最适合当前的任务。
通过将声明式特征与高级API结合,使查询优化器在执行期间可以利用这些优化方法,批处理框架看起来就更像MPP数据库了(井且能够实现性能相当)。同时,通过具有运行任意代码和读取任意格式数据的可扩展性,它们依然保持了灵活性的优势。

不同领域的专业化

传统上,MPP数据库满足了商业智能分析和商业报告的需求,另一个越来越重要的领域是统计和数值算法,过是诸如分类和推荐系统等机器学习应用所需要的。
批处理引擎正被用于日益广泛的算总领域的分布式执行。随着批处理系统获得更丰富的内置功能和高级声明式运算符,而MPP数据库也变得更具可编程性和灵活性,两者开始变得更加相似:最终,它们都是用于存储和处理数据的系统。