ITPub博客

首页 > 数据库 > 数据库开发技术 > Spark「并行」,就一定比「不并行」性价比更高吗?

Spark「并行」,就一定比「不并行」性价比更高吗?

原创 数据库开发技术 作者:安瑞哥是码农 时间:2024-09-12 10:02:01 0 删除 编辑


上篇文章测试了 Spark 如何用分布式读取 MySQL 的实现方案,并且演示了在当前表字段类型都不符合「分区字段」要求的情况下,可以通过怎么样的「骚操作」,来达到将数据平均切割的目的。


但利用这种分布式读取 MySQL 数据的方法,只是我们对程序优化的一种手段,最终能不能达到「节省硬件资源」或者「提高计算效率」才是我们追求的目的。


那经过上次对 MySQL 数据的切割之后,Spark 处理它需要的「硬件资源」到底有没有变少?以及对应的「计算效率」有没有变高?


这一次,我们一起来验证一下。



0. 不分区时需要资源跟效率


默认情况下,Spark 读 MySQL 只有 1 个分区,所以就要求这个分区能承载所有的数据量,记得当时要读取这张数据量为 1600w+



用特定的计算方式进行计算时,需要的「最小」内存为:


executor 内存量:2G。


--executor-memory 2g


占用的 yarn 总内存为:约3.5G



而当我们把原本的单个分区,给平均切成 10 个之后,需要的最小内存是多少?以及想要实现最高效的计算效率,应该采用什么样的并行策略呢?



1. 采用单个并行时——基准测试


作为对照,第一次测试,我们对 Spark 采用单并行策略,也就是

「1个 executor,配 1个 CPU」。


1个并行运行时


经过实测,能成功执行完任务,需要的 executor 内存设置为:512MB。


--executor-cores 1 --num-executors 1 --driver-memory 512m


占用的 yarn 总内存为:不到2G。



任务执行时间:约2分钟半(多次测量取平均值)。



小结:1个并行度时,相比之前 MySQL 采用默认分区(1个分区),Spark 需要的内存量大幅减少(少1.5G),但任务执行效率也由原来的约 1分钟,提高到约 2.5分钟。



2. 单 executor,2 CPU 时


在上一个基准测试时,细心的同学可能发现了一个问题,那就是既然原来 1 个分区时,需要的 executor 内存大小为 2G,那么现在把数据切成了平均 10份,理论上单个 executor 需要的内存就只需要大概 200M 就够了呀?


那为毛上面还要把 executor 的内存设置为 512M 呢?


如果你有这个思考,说明前面几期的测试结论,你真的看进去了,这里之所以单个 executor 给设置 512M,而不是 200M,原因在于:


yarn 不允许,目前我的集群环境,yarn 允许设置的最小 executor 内存大小,只能是 512M!


既然让 512M 的 executor 只跑 1 个分区的数据有些浪费了,那我们就让它并行跑 2个(或者更多个),这样一来,平均单个分区分摊的内存,就是 256M 了(或者更少)。


于是,当前对于 executor 的内存和并行度设置为:


--executor-cores 2 --num-executors 1 --driver-memory 512m


这样一来,虽然只有 1个 executor ,但并行度变成了2:


2个并行运行时


此时 yarn 占用的总内存不变,不变。



但因为并行度由原来的 1个,提高为 2个,所以执行效率肯定会提高。



由原来的 2.5分钟,提高到只需要 1.6分钟(多次执行取的平均值)。


小结:通过分析单个 executor 有富余的内存空间,提高单个 executor 的并行度,在硬件资源消耗不变的情况下,可以有效提高任务的执行效率。



3. 单 executor,3 CPU 时(依然可行)


这个时候,executor 的内存和并行度设置为:


--executor-cores 3 --num-executors 1 --driver-memory 512m


单个 executor 的并行度为 3:


3个并行运行时


yarn 占用的总内存量,依然跟上面一样保持不变(不到2G)。


按理说,这个时候,Spark 每个 partition 平均分得的内存量就为 512/3 MB。


那是不是就不够了呢?


结果你猜怎么着,它依然能跑成功(没有出现我认为的 OOM),但有一点可以确定的是,这个时候,单个 partition 的内存肯定是非常紧张的。



这个时候,整个任务执行时间,再一次缩短为 1.2分钟。


小结:通过单 executor 设置 3个并行度,依然在硬件资源消耗不变的情况下能跑成功,且执行效率,比 2个并行更高一些。



4. 单 executor,4 CPU 时(扛不住了)


如果说,上一个设置单 executor 3 个 CPU 是当前这个任务能承载的内存极限(512MB),那么当前的这个设置,毋庸置疑就是在找死。


事实证明,这一次,雀食行不通了,OOM 它终于来了。

 


5. 最高效且最节省资源的配置(3 executor,3 cpu)


如果现在要你对当前这个任务,用效率最高,且最节省资源的方式把它给跑起来,应该怎么设置?


应该这么来:


--executor-cores 3 --num-executors 3 --driver-memory 512m


你觉得呢?


这个时候,权衡资源最省、且效率最高时的最大并发为:9个。


9个并行运行时


这个时候 yarn 占用的总内存大小为:约3.8G



(这里怀疑是 yarn 显示的 bug,消耗的 CPU 应该为 10 才对)


执行效率为:约 1分钟。



小结:通过权衡资源消耗的最小化,以及执行效率的最大化,对于当前任务,需要 3个 executor,以及每个 executor 3个 CPU,消耗约3.8G 内存。



最后


所以,经过这样一番折腾,发现什么问题没?


在什么都不调整,不设置的情况下(单数据分区),面对相同的逻辑计算,把任务跑成功时。


任务执行效率为:不到 1 分钟。


占用 yarn 总资源为:约3.5G。

而现在呢?


分布式是实现了,但就算我们「挖空心思」,以「性价比」最高的方式来跑这个任务,在所消耗的硬件资源,比之前什么都不做还要高的的情况下,执行效率也就是勉强打个平手。


说明什么?


说明分布式的计算方式,并不是在任何情况下都是最优解决方案,如果数据量相对比较小,且单个节点的算力能完全能 hold 住,那用「单节点方式」可能更划算。


毕竟,分布式情况下,天然需要的「基础硬件成本」、和「必要的网络通信开销」是任何一个分布式任务绕不开的。


所以,基于什么样的数据量,用什么样的计算方式,你心里有谱了吗?




你可以添加我的私人微信,拉你入技术讨论群,跟一群热爱技术的小伙伴一起成长...


原文作者:安瑞哥是码农;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-02-16

  • 博文量
    228
  • 访问量
    115417