我是Spark的初学者,我正在努力理解它的体系结构。我知道,在理想的情况下,集群管理器会将任务分配给执行器,这些执行器在处理所需数据的同一节点上运行。但是,如果存在数据的节点没有任何可用的执行器,该怎么办?
spark如何处理同一位置的数据背后的大致想法是:
如果使用SparkSession提供的工具读取DataFrame(请参阅DataFrameReader文档),则会创建一个执行图,该执行图将尝试读取本地数据节点。也就是说,每个Spark执行器将读取驻留在分布式存储的本地执行器部分的数据:例如本地HDFS块。这要求您在数据存储中具有分区信息,并使用此信息创建DataFrameReader。这是将Spark用于大数据的正确方式,因为它允许近乎任意的缩放。
Rick Moritza从这里
在某些用例中,数据与spark集群不在同一位置,spark必须找出将数据提交给执行器的最佳方法。另一个用例正是您所说的,一个节点没有足够的资源来启动执行器。对于所有这些用例,spark按照以下规则处理问题:
数据局部性会对Spark作业的性能产生重大影响。如果数据和对其进行操作的代码在一起,那么计算往往很快。但是,如果代码和数据是分开的,那么其中一个必须移动到另一个。通常情况下,将序列化代码从一个地方运送到另一个地方比将数据块运送到一个地方更快,因为代码大小比数据小得多。Spark围绕这一数据局部性的一般原则构建其调度。
数据局部性是指数据与处理它的代码的距离。基于数据的当前位置,有几个级别的局部性。按从最近到最远的顺序:
- PROCESS_LOCAL-数据与运行代码位于同一JVM中。这是最好的地方
- NODE_LOCAL-数据位于同一节点上。示例可能在同一节点上的HDFS中,或者在同一个节点上的另一个执行器中。这比PROCESS_LOCAL慢一点,因为数据必须在进程之间传输
- NO_PREF-从任何地方都可以同样快速地访问数据,并且没有位置偏好
- RACK_LOCAL—数据位于同一个服务器机架上。数据位于同一机架上的不同服务器上,因此需要通过网络发送,通常通过单个交换机发送
- ANY-数据在网络的其他位置,而不是在同一机架中
Spark更喜欢在最佳位置级别安排所有任务,但这并不总是可能的。在任何空闲执行器上都没有未处理的数据的情况下,Spark会切换到较低的位置级别。有两种选择:a)等待繁忙的CPU释放出来,在同一服务器上的数据上启动任务,或者b)立即在更远的地方启动新任务,需要将数据移动到那里。
Spark通常会等待一段时间,希望繁忙的CPU能够腾出空间。一旦超时,它就会开始将数据从远处移动到空闲的CPU。每个级别之间的回退等待超时可以单独配置,也可以全部配置在一个参数中;有关详细信息,请参阅配置页面上的park.locality参数。如果您的任务很长并且位置不好,则应该增加这些设置,但默认设置通常效果良好。
并且优选本地数据排序的差异:PROCESS_local>NODE_LOCAL>NO_PREF>RACK_LOCAL
从这里
如果数据与您的spark应用程序不在同一位置,例如,您从S3读取数据:
S3的主要问题是,消费者不再具有数据本地性,所有读取都需要通过网络传输数据,而S3性能调优本身就是一个黑匣子。当使用HDFS并获得完美的数据局部性时,可以在某些实例类型上获得~3GB/节点的本地读取吞吐量(例如,i2.8xl,每个核心大约90MB/s)。DBIO是我们的云I/O优化模块,它为S3提供了优化的连接器,可以在i2.8xl上维持约600MB/s的读取吞吐量(每个内核约20MB/s)。
也就是说,在每个节点的基础上,HDFS可以产生比S3高6X的读取吞吐量。因此,考虑到S3比HDFS便宜10倍,我们发现S3在每美元的性能上几乎是HDFS的2倍。
然而,S3的一大好处是,我们可以将存储与计算分离,因此,我们可以在更短的时间内启动一个更大的集群,以提高吞吐量,达到允许的物理限制。这种计算和存储的分离还允许不同的Spark应用程序(如数据工程ETL作业和专门的数据科学模型训练集群)在自己的集群上运行,从而防止影响多用户固定大小Hadoop集群的并发问题。这种分离(以及对不同工作负载的灵活适应)不仅降低了成本,而且改善了用户体验。
从这里