弹性分布式数据集:一种对内存集群计算的容错抽象(三)

来源:互联网 发布:rgb转16进制java 编辑:程序博客网 时间:2024/05/16 14:03

说明

本文是翻译自讲述Spark核心设计思想的经典论文“Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing”。在翻译的过程中,更系统的理解了Spark中的RDD设计起源、优点与实际应用场景。阅读这样的经典文章,读者也能了解到一个大型的数据处理系统,是怎样被设计出来的。我在博客中计划用3篇博文来完成这个翻译,本篇为第3/3篇(最后一篇),如下既是正文。

  • 第1篇在这里:http://blog.csdn.net/ybdesire/article/details/78078764

  • 第2篇在这里:http://blog.csdn.net/ybdesire/article/details/78138084

6. 评估

我们通过对Amazon EC2的一系列实验,以及用户应用的基准评估了Spark和RDD。总的来说,我们的结果如下:

  • 在迭代机器学习和图形应用中,Spark的性能优于Hadoop高达20倍。速度的提高,是通过将内存中的数据存储为Java对象来避免I/O和反序列化成本。

  • 我们用户写的应用程序执行和扩展良好。 特别是,我们使用Spark来加快在Hadoop上运行的分析报告(40倍)。

  • 当节点出现故障时,Spark可以通过重建丢失的RDD分区,来快速恢复。

  • Spark可用于以5 - 7秒的延迟交互式查询1 TB数据集。

我们首先介绍迭代机器学习(6.1)和PageRank(6.2)与Hadoop做比较的基准。然后我们评估Spark(6.3)中的故障恢复,和数据集不适合内存的行为(6.4)。最后,我们讨论用户应用的结果(6.5)和交互式数据挖掘的结果(6.6)。

除非另有说明,否则我们的测试使用具有4个内核的m1.xlarge EC2节点和15 GB的RAM。 我们使用HDFS存储,256 MB的块存储。 在每次测试之前,我们清除了操作系统缓冲区高速缓存,准确地测量IO成本。

6.1 迭代机器学习应用

我们实现了两种迭代机器学习应用:logistic回归和k-means,用于比较下面的系统的性能:

  • Hadoop:Hadoop 0.20.2稳定版
  • HadoopBinMem:Hadoop部署,可在第一次迭代中将输入数据转换为低开销二进制格式,以消除稍后的文本解析,并将其存储在内存中的HDFS实例中。

  • Spark:本文的RDD实现。

我们将两种算法都放到25-100台机器,在100GB数据集上运行了10次迭代。两个应用程序的关键区别在于它们每字节数据执行的计算量。k-means的迭代时间有计算量支配,但logistic回归计算密集程度较低,因此对反序列化和I/O所花费的时间更为敏感。

由于典型的学习算法需要数十次迭代来收敛,所以我们分别报告第一次迭代次数,和后续迭代次数。我们发现通过RDD共享数据大大加快了未来的迭代。

首次迭代:所有这三个系统在第一次迭代中读取HDFS的文本输入。 如图7条形图所示,Spark在实验中比Hadoop更快。这种差异,是由于Hadoop在master和worker之间的心跳协议中,有信令开销。HadoopBinMem是最慢的,因为它运行了一个额外的MapReduce作业,来将数据转换为二进制,并且必须将该数据跨网络写入复制的内存中的HDFS实例。

后续迭代:图7还显示了后续迭代的平均运行时间,而图8显示了如何按照集群大小进行缩放。

这里写图片描述

理解加速:我们惊奇地发现,Spark在二进制数据(Hadoop in Men)的内存存储器中以20倍的优势超越了Hadoop。在HadoopBinMem中,我们使用了Hadoop的标准二进制格式(SequenceFile)和256 MB(大块)的大小,我们强制HDFS的数据目录位于内存中的文件系统中。 然而,由于以下几个因素,Hadoop仍然运行较慢:

  • (1)Hadoop软件堆栈的最小开销。
  • (2)提供数据时HDFS的开销。
  • (3)将二进制记录转换为可用的内存中Java对象的反序列化成本。

我们依次调查了这些因素。为了测量(1),我们运行了无操作的Hadoop作业,并发现这些工作至少需要25s的时间才能完成作业设置,启动任务和最低要求的清理。关于(2),我们发现HDFS执行多个内存副本与校验和来为每个块提供服务。

最后,为了测量(3),我们在单个机器上运行微基准,以各种格式对256 MB输入进行逻辑回归计算。特别地,我们比较了处理来自HDFS(HDFS堆栈中的开销将显示)和内存中本地文件(内核可以非常有效地将数据传递到程序)的文本和二进制输入的时间。

我们在图9中展示了这些测试的结果。内存HDFS和本地文件之间的差异表明,通过HDFS读取引入了2秒的开销,即使数据位于本地机器上的内存中。文本和二进制输入之间的差异表明解析开销是7秒。最后,即使从内存中读取文件,将预解析的二进制数据转换为Java对象也需要3秒钟,这仍然与逻辑回归本身一样昂贵。通过将RDD元素直接存储在内存中作为Java对象,Spark避免了所有这些开销。

这里写图片描述

6.2 PageRank

我们使用54GB维基百科数据,比较了Spark与Hadoop对PageRank的性能。我们运行了10次迭代的PageRank算法来处理大约400万篇文章的链接图。图10显示,使用内存存储,使Spark的速度,是在30个节点上的Hadoop上的2.4倍。此外,如第3.2.2节所述,控制RDD的分区使其在迭代中保持一致,提高了加速到7.4倍。 结果也几乎线性地缩小至60个节点。

这里写图片描述

我们还对第7.1节中描述的使用Pregel over Spark的实现编写的PageRank版本进行了评估。迭代次数类似于图10中的迭代次数,但是延长约4秒,因为Pregel在每次迭代上运行额外的操作,以使顶点“投票”是否完成该作业。

6.3 故障恢复

我们使k-means应用程序中的节点故障后,测量使用谱系重建RDD分区的成本。图11比较了正常运行情况下75节点集群上k-means的10次迭代的运行时间,其中节点在第6次迭代开始时失败。没有任何故障时,每次迭代由400个任务处理100 GB的数据组成。

这里写图片描述

直到第5次迭代结束,迭代次数约为58秒。 在第六次迭代中,其中一台机器被杀死,导致在该机器上运行的任务和该处存储的RDD分区丢失。Spark在其他机器上并行重新运行这些任务,在这些机器上重新读取相应的输入数据和重建的RDD,从而将迭代时间增加到80s。 一旦丢失的RDD分区被重构,迭代时间可以恢复到58秒。

请注意,使用基于检查点的故障恢复机制,恢复可能需要至少重新运行几次迭代,这取决于检查点的频率。此外,系统需要通过网络将应用程序的100 GB工作集(文本输入数据转换为二进制)复制,并将消耗两倍于Spark的内存以将其复制到RAM中,或者必须等待写入100 GB到磁盘。 相比之下,我们的示例中的RDD的谱系图的大小都小于10 KB。

6.4 内存不足时的行为

到目前为止,我们确保了集群中的每台机器都有足够的内存来存储所有RDD。一个自然的问题是如果没有足够的内存来存储作业的数据,Spark如何运行。在本实验中,我们配置了Spark不要使用超过一定百分比的内存来存储每台机器上的RDD。我们在图12中呈现了用于逻辑回归的各种存储空间的结果。我们看到,性能以较少的空间正常降级。

这里写图片描述

6.5 基于Spark构建的用户应用

In-Memory分析:视频分销公司Conviva Inc,使用Spark来加速先前在Hadoop上运行的大量数据分析报告。例如,一个report作为一系列用于计算客户的各种统计信息的Hive查询。这些查询都在同一个数据子集(与客户提供的过滤器匹配的记录)上工作,但在不同的分组字段上执行了聚合(平均值,百分位数和COUNT DISTINCT),需要单独的MapReduce作业。通过在Spark中实现查询并将其中共享的数据子集加载到RDD中,公司能够将报告加速40倍。现在,仅使用两台Spark机器,在30分钟内,就可以完成在Hadoop集群上运行20个小时的200 GB压缩数据报告。此外,Spark程序只需要96 GB的RAM,因为它只存储与RDD中的客户过滤器匹配的行和列,而不是整个解压缩的文件。

交通模型:伯克利移动千年计划中的研究人员,并行化了一种从零星汽车GPS测量中,推断道路交通拥堵的学习算法。源数据是一个大城市的10,000个连接道路网络,以及配备GPS的汽车的点对点行程时间的60万个样本(每个路径的旅行时间可能包括多个道路连接)。使用流量模型,系统可以估计在各个道路链路之间行驶的时间。研究人员使用期望最大化(EM)算法对该模型进行了训练,该算法重复迭代了两个map和reduceBeyKey步骤。该应用程序从20到80个节点几乎线性扩展,每个节点有4个CPU,如图13(a)所示。

这里写图片描述

Twitter垃圾邮件分类:伯克利的Monarch项目使用Spark来识别Twitter消息中的垃圾邮件。他们实现了一个逻辑回归分类器,类似于第6.1节中的示例,但是他们使用一个分布式的reduceByKey并行对梯度向量求和。在图13(b)中,我们显示了在50 GB数据子集中训练分类器的结果:250,000个URL和107个特征/维度,与网络的每个URL的网页和内容属性相关。由于每次迭代的固定通信成本较高,结果并不是完全线性。

6.6 交互式数据挖掘

为了证明Spark的交互式查询大数据集的能力,我们使用它来分析维基百科页面视图日志(2年数据,1TB)。对于本实验,我们使用了100平方米的大型EC2实例,每个实例有8个核和68GB的RAM。我们运行查询以查找:(1)所有页面,(2)标题与给定单词匹配的页面,以及(3)给定单词与标题部分匹配的页面。 每个查询都扫描整个输入数据。

图14显示了查询对完整数据集(数据的一半和十分之一)的响应时间。Spark在1TB的数据上执行查询,也只花费5-7秒的时间。这比查询存储在磁盘上的数据速度要快一个数量级;例如,从磁盘查询1TB的数据需要花费170秒。这表明RDD使Spark成为交互式数据挖掘的强大工具。

7. 讨论

尽管RDD由于其不可变性和粗粒度转换,似乎只提供了有限的编程接口,但我们发现它适用于广泛的应用。特别地,RDD可以用于表示惊人数量的(迄今为止已被提出为单独的框架)集群编程模型,允许用户在一个程序中组合这些模型(例如,运行MapReduce操作来构建图表,然后运行Pregel) 并在他们之间共享数据。在本节中,我们将讨论RDD可以表达哪些编程模型以及为什么它们可以被广泛应用(7.1)。此外,我们还讨论了我们正在追求的RDD中谱系信息的另一个优点,这有助于这些模型的调试(7.2)。

7.1 表示现有的编程模型

RDD可以有效地表示迄今为止被独立提出的一些集群编程模型。所谓“有效”,我们的意思是,不仅可以使用RDD来产生与这些模型中编写的程序相同的输出,而且RDD还可以捕获这些框架执行的优化,例如将特定数据保存在内存中,减少分区间通信,并从故障中有效地恢复。可以用RDD有效表示的模型包括:

  • MapReduce:这个模型可以用在Spark中的flatMapgroupByKey操作来表示,如果有一个组合器,可以使用reduceByKey

  • DryadLINQ:DryadLINQ系统比MapReduce在更通用的Dryad运行时提供了更广泛的运算符,但这些都是直接对应于Spark(mapgroupByKeyjoin等)中的RDD转换的批量运算符。

  • SQL:像DryadLINQ表达式一样,SQL查询对记录集执行数据并行操作。

  • Pregel:Google的Pregel是迭代图应用的专用模型,它与其他面向集合的编程模型看起来完全不同。在Pregel中,程序作为一系列协调的“超级步骤”运行。在每个超级步骤中,图中的每个顶点运行一个用户函数,可以更新与顶点相关联的状态,更改图形拓扑,并将消息发送到其他顶点以供下一个超级步骤使用。该模型可以表示许多图算法,包括最短路径,二分匹配和PageRank。

促使我们用RDD实现此模型的关键点,是Pregel在每次迭代时,对所有顶点都使用相同的用户函数。因此,我们可以将每个迭代的顶点状态存储在RDD中,并执行批量转换(flatMap)以应用此函数并生成消息的RDD。然后,我们可以将这个RDD与顶点状态一起进行消息交换。同样重要的是,RDD允许我们保持像Pregel这样的内存中的顶点状态,通过控制它们的分区来最小化通信,并支持部分故障恢复。 我们已经将Pregel作为Spark的200线图书馆,并将读者引用到[33]以了解更多细节。

  • 交互式MapReduce:几个最近提出的系统,包括HaLoop [7]和Twister [11],提供了一个迭代的MapReduce模型,其中用户给系统一系列MapReduce作业循环。系统使数据在整个迭代中保持一致,Twister也可以将其保存在内存中。 这两个优化都可以用RDD表达,我们可以使用Spark实现HaLoop作为200行库。

  • 批量流处理:研究人员最近为应用程序提出了几种增量处理系统,可以使用新的数据定期更新结果[21,15,14]。例如,每15分钟更新关于广告点击的统计信息的应用程序,应该能够将来自前15分钟窗口的中间状态与来自新日志的数据进行组合。这些系统执行类似于Dryad的批量操作,但是将应用程序状态存储在分布式文件系统中。 将中间状态放置在RDD中可加快处理速度。

  • RDD表达能力的解释:为什么RDD能表示不同的编程模型?原因是RDD的局限性,对很多并行应用程序来说,都只有很少的影响。特别地,尽管RDD只能通过批量转换来创建,但许多并行程序自然地将相同的操作应用于许多记录,使得它们易于表达。类似地,RDD的不变性不是障碍,因为可以创建多个RDD来表示相同数据集的版本。 事实上,今天的许多MapReduce应用程序都运行在不允许更新文件的文件系统上,如HDFS。

最后一个问题是为什么以前的框架没有提供相同的一致性。我们认为这是因为这些系统探索了MapReduce和Dryad在处理方面不能很好地处理的具体问题,比如迭代,而没有观察到这些问题的常见原因是缺乏数据共享抽象。

7.2 利用RDD进行调试

虽然我们最初设计RDD是确定性重新计算容错的,但此属性也有助于调试。 特别地,通过记录在作业期间创建的RDD的谱系,可以(1)稍后重建这些RDD,并让用户以交互方式进行查询,并且(2)在单个过程调试器中重新运行任务, 重新计算它依赖的RDD分区。与普通分布式系统[13]的传统重播调试器不同,它必须捕获或推断出多个节点之间的事件顺序,因为只需要记录RDD谱系图,所以这种方法几乎可以增加零记录开销。基于这些想法,我们正在开发一个Spark调试器 [33]。

8. 相关工作

集群编程模型:在集群编程模型相关的工作主要分为那么几类。第一类,数据流模型,比如MapReduce,Dryad,Ciel。他们都对数据处理提供了丰富的操作,并且通过稳定的存储系统进行共享。RDD代表了比稳定存储更有效的数据共享抽象,因为它们避免了数据复制,I/O和序列化的成本。

其次,数据流系统的几个高级编程接口,包括DryadLINQ和FlumeJava,提供了语言集成的API,用户通过运算符操作“并行集合”,如map和join。然而,在这些系统中,并行集合表示磁盘上的文件或用于表达查询计划的临时数据集。虽然系统将在同一查询中(例如,映射跟另一个映射)在运营商之间管理数据,但是它们无法跨查询有效共享数据。我们基于Spark的API在并行集合模型上,由于其方便性,并且不为语言集成接口提出新颖性,而是通过提供RDD作为该接口后面的存储抽象,我们允许它支持更广泛的应用程序类。

第三类系统为需要数据共享的特定应用类提供高级接口。例如,Pregel支持迭代图应用,而Twister和HaLoop则是迭代MapReduce运行时。然而,这些框架为他们支持的计算模式隐含地执行数据共享,并且不提供一种通用的抽象来让用户在她选择的操作之间共享她选择的数据。例如,用户不能使用Pregel或Twister将数据集加载到内存中,然后决定要在其上运行什么查询。 RDD显式提供分布式存储抽象,从而可以支持这些专门系统无法捕获的应用程序,如交互式数据挖掘。

最后,一些系统暴露共享的可变状态,以允许用户执行内存中的计算。例如,Piccolo允许用户运行并行功能,读取和更新分布式哈希表中的单元格。 分布式共享内存(DSM)系统和键值存储(如RAMCloud)提供了类似的模型。 RDD与两种系统有所不同。首先,RDD提供基于诸如地图,排序和连接等运算符的更高级别的编程接口,而Piccolo和DSM中的接口只是对表格单元的读取和更新。 第二,Piccolo和DSM系统通过检查点和回滚来实现恢复,这在许多应用中比RDD的基于谱系的策略更昂贵。 最后,如第2.3节所述,RDD还提供了超过DSM的其他优势,如分流减缓。

缓存系统:Nectar可以通过使用程序分析识别常见的子表达式,在DryadLINQ作业中重用中间结果。 这种能力将迫切需要添加到基于RDD的系统中。 但是,Nectar不提供内存中缓存(它将数据放置在分布式文件系统中),也不允许用户明确控制哪些数据集持久化以及如何分配它们。 Ciel和FlumeJava同样可以缓存任务结果,但不提供内存缓存或显式控制哪些数据被缓存。

Ananthanarayanan 等人已经提出向分布式文件系统添加内存缓存以利用数据访问的时间和空间局部性。 虽然此解决方案可以更快地访问已存在于文件系统中的数据,但是作为RDD在应用程序中共享中间结果的方法并不是很有效,因为它仍然需要应用程序将这些结果写入文件系统的阶段之间。

谱系图:收集数据的谱系或来源信息长期以来一直是科学计算和数据库中的研究课题,用于解释结果,允许他人复制的应用程序,如果在工作流程中发现错误,则重新计算数据,如果数据集丢失,我们将读者参考并进行这项工作的调查。 RDD提供了一种并行编程模型,其中细粒度谱系捕获成本低廉,因此可用于故障恢复。

我们基于谱系的恢复机制也类似于在MapReduce和Dryad中的计算(作业)中使用的恢复机制,它跟踪任务的DAG之间的依赖关系。 然而,在这些系统中,作业结束后,谱系信息将丢失,需要使用复制的存储系统来跨计算共享数据。 相比之下,RDD适用于跨计算有效地保留内存中数据,而不需要复制和磁盘I / O的成本。

关系数据库:RDD在概念上类似于数据库中的视图,并且持久性RDD类似于实例化视图。 然而,像DSM系统一样,数据库通常允许对所有记录进行细粒度的读写访问,需要记录操作和数据以进行容错和额外的开销以保持一致性。 RDD的粗粒度转换模型不需要这些开销。

9. 结论

我们提出了弹性分布式数据集(RDD),这是一种高效,通用和容错的抽象,用于在集群应用程序中共享数据。RDD可以表示广泛的并行应用程序,包括已经提出用于迭代计算的许多专门的编程模型,以及这些模型不能捕获的新应用程序。与集群的现有存储抽象不同,需要对容错进行数据复制,RDD提供基于粗粒度转换的API,可以使用谱系有效地恢复数据。我们已经在一个称为Spark的系统中实现了RDD,它在迭代应用程序中优于Hadoop高达20倍,可以交互使用来查询数百GB的数据。

我们已经在spark-project.org上开放Spark,作为可扩展数据分析和系统研究的工具。

关键语句摘录

  • RDD

    • We have presented resilient distributed datasets (RDDs), an efficient, general-purpose and fault-tolerant abstraction for sharing data in cluster applications.
    • RDDs offer an API based on coarsegrained transformations that lets them recover data efficiently using lineage.
  • 调度

    • Our scheduler assigns tasks to machines based on data locality using delay scheduling

感谢

本文翻译大量借助了Google Translate,感觉目前Google Translate的翻译准确度已经超过80%了,在此感谢!

阅读全文
0 0