任何水平缩放 Spark 的技巧
Posted
技术标签:
【中文标题】任何水平缩放 Spark 的技巧【英文标题】:Any tips for scaling Spark horizontally 【发布时间】:2018-05-17 05:58:23 【问题描述】:在将 Spark 执行从几个大型节点转移到许多较小的节点时,是否有人有任何提示?
我正在运行一个有 4 个执行器的系统,每个执行器有 24Gb 的内存和 12 个内核。如果我尝试将其扩展到 12 个执行程序,每个执行程序 4 个内核和 8 Gb 内存(相同的总 RAM,相同的总内核,只是分布不同),我会遇到内存不足错误:
Container killed by YARN for exceeding memory limits. 8.8 GB of 8.8 GB physical memory used.
我将分区数量增加了 3 倍以创建更多(但更小)的分区,但这没有帮助。
在尝试水平缩放火花时,有人有任何提示和技巧吗?
【问题讨论】:
【参考方案1】:这是一个相当广泛的问题,Spark 中的执行者规模调整是一种非常复杂的黑魔法,而 例如在 2015 年正确的经验法则现在已经过时了 strong>,正如我所说的任何内容都将在 6 个月内随着 Spark 的下一个版本过时。很大程度上取决于您正在做什么以及避免数据中的关键偏差。
这是一个开始学习和发展自己理解的好地方: https://spark.apache.org/docs/latest/tuning.html
Slideshare 上还有大量关于调整 Spark 的演示文稿,请尝试阅读/观看最新的演示文稿。任何超过 18 个月的都值得怀疑,超过 2 年的则忽略。
我会假设您至少使用 Spark 2.x。
您遇到的错误确实是由于执行程序大小调整不当造成的。正在发生的事情是,您的执行者试图一次做太多事情,并在内存不足时将自己陷入困境。
在所有其他条件相同的情况下,这些是我应用它们时的当前经验法则:
简短版
3 - 4 个虚拟(超线程)内核和 29GB 的 RAM 是合理的默认执行程序大小(稍后我将解释原因)。如果您一无所知,请妥善划分您的数据并使用它。 您通常应该将数据分区大小(在内存中)的目标设为 ~100MB 到 ~3GB我应用的公式
执行器内存 = 执行器核心数 * 分区大小 * 1.3(安全系数)
分区大小 = 磁盘上的数据大小 / 分区数 * 请求率
反序列化比率是磁盘上数据大小与内存中数据大小的比率。相同数据的 Java 内存表示往往比磁盘大一点。
您还需要考虑您的数据是否经过压缩,Parquet 和 ORC 等许多常见格式使用 gzip 或 snappy 等压缩。
对于快速压缩的文本数据(非常容易压缩),我使用 ~10X - 100X。 对于混合了文本、浮点数、日期等的快速压缩数据,我通常看到 3X 到 15X 之间。
执行器核心数 = 3 到 4 执行程序核心完全取决于您的计算是计算密集型还是内存密集型。试验一下,看看什么最适合您的用例。我从来没有见过有人了解 Spark 提倡超过 6 个内核。
Spark 足够聪明,可以利用数据局部性,因此您的执行程序越大,您的数据为PROCESS_LOCAL 的机会就越大 在一定程度上,更多的数据局部性是好的。
当 JVM 变得太大 > 50GB 时,它会开始超出最初设计的范围运行,并且根据您的垃圾收集算法,您可能会开始看到性能下降和 GC 时间变长。
https://databricks.com/blog/2015/05/28/tuning-java-garbage-collection-for-spark-applications.html
Java 中也有一个性能技巧,如果你的 JVM 小于 32GB,你可以使用 32 位压缩指针而不是 64 位指针,这样可以节省空间并降低缓存压力。
https://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html https://blog.codecentric.de/en/2014/02/35gb-heap-less-32gb-java-jvm-memory-oddities/
YARN 也会为您的执行程序大小增加 7% 或 384MB 的 RAM(以较大者为准)以用于开销/安全因素,这就是 29GB 经验法则的来源:29GB + 7% ~= 32GB
您提到您使用的是 12 核、24GB RAM 执行器。这对我来说是一个危险信号。
为什么?
因为执行器中的每个“核心”都会被分配一个“任务”。一项任务相当于计算一个分区从“阶段”A到“阶段”B的转换所需的工作。
https://jaceklaskowski.gitbooks.io/mastering-apache-spark/content/spark-taskscheduler-tasks.html https://jaceklaskowski.gitbooks.io/mastering-apache-spark/content/spark-DAGScheduler-Stage.html
如果您的执行程序有 12 个内核,那么它将尝试以 24GB 的内存预算同时执行 12 个任务。 24GB / 12 核 = 每核 2GB。如果您的分区大于 2GB,您将收到内存不足错误。如果特定的转换使输入的大小加倍(即使是中间),那么您也需要考虑到这一点。
【讨论】:
以上是关于任何水平缩放 Spark 的技巧的主要内容,如果未能解决你的问题,请参考以下文章