像原设计者一样深入理解 Spark

在数据领域可用的框架中 , 只有少数框架在采用和交付方面达到了 Spark 的水平 。 显然 , 该框架已经成为一个赢家 , 特别是在数据工程方面 。 本文是对 Spark 组件的一个非常简单的介绍 , 其主要目的是提供对 Spark 架构的一般理解 。
本文最初发布于 Towards Data Science 博客 , 由 InfoQ 中文站翻译并分享 。
为什么要了解 Spark?在数据领域可用的框架中 , 只有少数框架在采用和交付方面达到了 Spark 的水平 。 显然 , 该框架已经成为一个赢家 , 特别是在数据工程方面 。
如果你正在阅读这篇文章 , 这意味着你已经理解了我这样说的原因 , 所以我们直接进入主题 。
为什么要了解 Spark 的内部构造?有人可能会说 , 开车并不需要了解发动机的工作原理 , 是这样 。 不过 , 有人可能会说 , 了解发动机会让你成为更好的驾驶员 , 因为你将能够了解整个车辆的性能、局限性和根本问题 。
同理 , 你不需要了解 Spark 的内部构造就可以使用它提供的 API 。 但是 , 如果你了解的话 , 就可以减轻糟糕的性能和隐藏的 Bug 所带来的许多痛苦 。 此外 , 你还将掌握在整个分布式系统领域随处可见的概念 。
方法在我看来 , 学习有两个方面: 知识 和 技术。 前者涉及到通过书本、结构化课程等形式获取知识 。 它更关注 是什么。 后者与技能有关 , 即“边做边学” , 更侧重于 如何做。 这是我们这里要探讨的 。
我们将从每个初学者都能解决的一个简单问题开始 , 然后逐步演进以说明 Spark 的架构设计 。 在这个过程中 , 我们还将了解 HDFS (部分人称为 Hadoop) , 因为它是一个非常适合 Spark 的平台 。
为了做到语言无关 , 本文使用的所有代码都是伪代码 。
问题你刚入职并分得了一项简单的任务: 数一数数组中有多少个偶数。
你将从存储在本地文件系统中的 CSV 文件中读取该数组 。 不用多想 , 你可能会写出下面这段代码:
像原设计者一样深入理解 Spark文章插图
新需求一客户对上述解决方案的巨大成功感到满意 , 现在 , 他们认为可以把所有问题都交给你 , 所以他们要求你 计算这些偶数的平均值。
你肯定知道 SOLID 原则 , 特别是 单一责任原则, 即类或方法应该只因为一个原因更改 。 然而 , 你决定打破规则 , 像下面这样实现:
像原设计者一样深入理解 Spark文章插图
新需求二由于你做得快 , 人们又提出了另一个需求: 返回所有偶数的和。
这时 , 你不仅开始考虑 SOLID 原则 , 而且开始考虑事情进行的方式 。 你知道 , 通常情况下 , 一件事发生了一次并不意味着它会发生两次 , 但如果它发生了两次 , 第三次发生就在眼前 。 因此 , 你开始考虑实现更容易扩展的东西 , 并记起了 面向对象编程 中封装的概念 。
【像原设计者一样深入理解 Spark】另外 , 如果你实现了适当的抽象 , 那么当另一个需求出现时 , 你甚至可能不必更改你的实现 。
一套可以处理所有这些需求的抽象你开始考虑 , 如果他们让你数偶数 , 那么他们很可能会进一步问你奇数 , 或者是低于或高于某一个值的数 , 或在一个范围内的数 , 等等 。 因此 , 即使你是 YAGNI (你并不需要它)应用程序方面的专家 , 也会决定实现一些能够支持所有这些情况的东西 。
最后 , 你可以得出结论 , 所有这些操作都与从数组中过滤值有关 , 因此 , 你决定提供一个过滤器函数 , 它可以接收过滤器条件 , 而不是编写每种可能用到的过滤器 。
此外 , 为了简化设计 , 你决定在每次调用对象操作时更改其状态 。
像原设计者一样深入理解 Spark文章插图
接受新挑战你做到了 。 现在 , 你不仅实现了所有需求 , 而且还可以处理从数组中过滤值的新需求 。 如果客户现在想要奇数而不是偶数 , 那么它们唯一要做的就是向 filter 方法传递一个新条件 , 这样就行了 。 真神奇!但是 , 你一直在等待的新需求来了: 他们现在需要你处理一个 3TB 的数组。
你考虑放弃 。 你自己的硬盘只有 500GB , 所以你需要 6 台你这样的机器专门用于存储文件才能开始这项工作 。 但你的客户喜欢你 , 也很有说服力 , 他们给你加薪 , 还承诺提供 30 台新机器用于解决问题 , 而不是 6 台 。
划分有了 30 台新机器的使用权 , 你开始考虑如何解决这个问题 。 一台机器无法包含整个文件 , 因此你必须将其切成更小的块 , 然后分块放到新硬盘中 。 另外 , 由于你有足够的资源 , 作为备份 , 你还可以将相同的切片存储在多台机器上 。 也许每个切片两个拷贝 , 这意味着你可以在三个不同的地方找到这个切片 。