蚊章汇 - Sital Kedia, 王硕杰, Avery Ching
type: channel
link: https://linuxcn.bwsl.wang/author/621/
description: Sital Kedia, 王硕杰, Avery Ching
items: 60 TB 数据：Facebook 是如何大规模使用 Apache Spark 的

60 TB 数据：Facebook 是如何大规模使用 Apache Spark 的
type: item
date: 2017-06-23T17:55:00+08:00
description: Facebook 经常使用数据驱动的分析方法来做决策。在过去的几年，用户和产品的增长已经需要我们的分析工程师一次查询就要操作数十 TB 大小的数据集。我们的一些批量分析执行在古老的 Hive 平台（ Apache Hive 由 Facebook 贡献于 2009 年）和 Corona 上——这是我们定制的 MapReduce 实现。Facebook 还不断增加其对 Presto 的用量，用于对几个包括 Hive 在内的内部数据存储的 ANSI-SQL 查询。我们也支持其他分析类型，比如 图数据库处理 （ graph processing ） 和机器学习（Apache Giraph）和流（例如：Puma、Swift 和 Stylus）。同时 Facebook 的各种产品涵盖了广泛的分析领域，我们与开源社区不断保持沟通，以便共享我们的经验并从其他人那里学习。Apache Spark 于 2009 年在加州大学伯克利分校的 AMPLab 由 Matei Zaharia 发起，后来在2013 年贡献给 Apache。它是目前增长最快的数据处理平台之一，由于它能支持流、批量、命令式（RDD）、声明式（SQL）、图数据库和机器学习等用例，而且所有这些都内置在相同的 API 和底层计算引擎中。Spark 可以有效地利用更大量级的内存，优化整个 流水线 （ pipeline ） 中的代码，并跨任务重用 JVM 以获得更好的性能。最近我们感觉 Spark 已经成熟，我们可以在一些批量处理用例方面把它与 Hive 相比较。在这篇文章其余的部分，我们讲述了在扩展 Spark 来替代我们一个 Hive 工作任务时的所得到经验和学习到的教训。用例：实体排名的特征准备Facebook 会以多种方式做实时的 实体 （ entity ） 排名。对于一些在线服务平台，原始特征值是由 Hive 线下生成的，然后将数据加载到实时关联查询系统。我们在几年前建立的基于 Hive 的老式基础设施属于计算资源密集型，且很难维护，因为其流水线被划分成数百个较小的 Hive 任务。为了可以使用更加新的特征数据和提升可管理性，我们拿一个现有的流水线试着将其迁移至 Spark。以前的 Hive 实现基于 Hive 的流水线由三个逻辑 阶段 （ stage ） 组成，每个阶段对应由 entity\_id 划分的数百个较小的 Hive 作业，因为在每个阶段运行大型 Hive 作业 （ job ） 不太可靠，并受到每个作业的最大 任务 （ task ） 数量的限制。这三个逻辑阶段可以总结如下：过滤出非产品的特征和噪点。在每个（entity\_id, target\_id）对上进行聚合。将表格分割成 N 个分片，并通过自定义二进制文件管理每个分片，以生成用于在线查询的自定义索引文件。基于 Hive 的流水线建立该索引大概要三天完成。它也难于管理，因为该流水线包含上百个分片的作业，使监控也变得困难。同时也没有好的方法来估算流水线进度或计算剩余时间。考虑到 Hive 流水线的上述限制，我们决定建立一个更快、更易于管理的 Spark 流水线。Spark 实现全量的调试会很慢，有挑战，而且是资源密集型的。我们从转换基于 Hive 流水线的最资源密集型的第二阶段开始。我们以一个 50GB 的压缩输入例子开始，然后逐渐扩展到 300GB、1TB，然后到 20TB。在每次规模增长时，我们都解决了性能和稳定性问题，但是实验到 20TB 时，我们发现了最大的改善机会。运行 20TB 的输入时，我们发现，由于大量的任务导致我们生成了太多输出文件（每个大小在 100MB 左右）。在 10 小时的作业运行时中，有三分之一是用在将文件从阶段目录移动到 HDFS 中的最终目录。起初，我们考虑两个方案：要么改善 HDFS 中的批量重命名来支持我们的用例，或者配置 Spark 生成更少的输出文件（这很难，由于在这一步有大量的任务 — 70000 个）。我们退一步来看这个问题，考虑第三种方案。由于我们在流水线的第二步中生成的 tmp\_table2 表是临时的，仅用于存储流水线的中间输出，所以对于 TB 级数据的单一读取作业任务，我们基本上是在压缩、序列化和复制三个副本。相反，我们更进一步：移除两个临时表并整合 Hive 过程的所有三个部分到一个单独的 Spark 作业，读取 60TB 的压缩数据然后对 90TB 的数据执行 重排 （ shuffle ） 和 排序 （ sort ） 。最终的 Spark 作业如下：对于我们的作业如何规划 Spark？当然，为如此大的流水线运行一个单独的 Spark 任务，第一次尝试没有成功，甚至是第十次尝试也没有。据我们所知，从 重排 （ shuffle ） 的数据大小来说，这是现实世界…