SPark关于缓存&坑

本文详细介绍了Spark的执行流程、运行架构特点和关键概念,重点关注Spark的缓存机制。Spark默认情况下,RDD仅使用一次,再次使用需重新计算。缓存机制可以避免重复计算,提高性能,但如果不恰当使用可能导致数据一致性问题。文中通过实例分析了在多维度计算中,由于对象引用值的改变引起的数据误差,并提出了解决方案,包括不缓存、复制对象等策略。

SPark基本概念

对于Spark有一定了解的童鞋可以跳过前面基础概念的讲解,直接从下面的缓存部分开始看↓↓↓

Spark执行流程

Spark在执行Transformation类型操作时都不会立即执行,当遇到Action类型操作时,就会触发计算,每个action操作都会触发runJob操作,生成一个Job.在Driver中SparkContext根据RDD之间的依赖关系创建出DAG(有向无环图),DAGScheduler负责解析这个DAG,从当前Action方法向前回溯,如果遇到的是窄依赖则应用流水线优化,继续向前找,当碰到一个宽依赖时,就会把这个宽依赖之前的RDD组装成一个stage,再从当前宽依赖开始继续向前找,重复刚才的步骤,以此类推.每个stage由可以并发执行的一组task构成,一个partition对应一个task.DAGScheduler将stage划分完后,会将这组task提交到TaskScheduler去执行,任务会在Executor进程的多个Task线程上执行,完成Task任务后 将结果信息提交到ExecutorBackend中 他会将信息提交给TaskScheduler,TaskScheduler接到消息后通知TaskManager,移除该Task任务,开始执行下一个任务.TaskScheduler同时会将信息同步到TaskSet Manager中一份,全部任务执行完毕后TaskSet Manager将结果反馈给DAGScheduler,如果属于ResultTask 会交给JobListener.否则话全部任务执行完毕后写入数据.

Spark运行架构的特点

每个Application获取专属的Executor进程,该进程在Application期间一直驻留,并以多线程方式运行tasks。这种Application隔离机制有其优势,无论是从调度角度看(每个Driver调度它自己的任务),还是从运行角度看(来自不同Application的Task运行在不同的JVM中)。当前,这也意味着SparkApplication不能跨应用程序共享数据,除非将数据写入到外部存储系统。

几个名词解释

  1. Executor:
    在启动Spark程序时会指定num-executors executor数量,每个executor在yarn上就是一个container 也就是一个JVM
    通过executor-memory指定JVM内存大小
    spark提交命令
    而启动的一个Spark程序就是一个Application

  2. Job
    Spark是通过action算子触发真正的计算,每一个action操作会对应一个Job
    下面就是一个Application中的18个Job,也就是对应代码中的18个action操作
    一个Application中的18个Job

  3. Stage
    如上面所说的,在每个Job中从当前Action方法向前回溯,

<think>嗯,用户这次问的是Spark重新初始化的影响和结果。看起来用户对Spark的内部机制很感兴趣,可能是在调优或排查问题过程中遇到了相关场景。用户提供的参考资料很全面,涵盖了SparkContext初始化、任务提交、配置参数等核心内容。特别是引用[4]提到applicationId的唯一性,引用[2]强调SparkContext是访问集群的入口,这些对回答问题很关键。从用户的问题表述来看,ta应该具备一定的Spark基础,知道“重新初始化”这个操作的存在。但可能在实际操作中踩了,比如发现重新创建SparkContext时报错,或者好奇为什么不能随意重建连接。需要重点解释的几个方面:技术限制上,Spark的设计本身禁止创建多个SparkContext实例(引用[2]提到SparkContext是访问集群的起点),底层Netty传输框架会冲突。这点必须强调,因为很多开发者习惯像初始化普通对象那样处理SparkContext。资源消耗方面要量化说明:以广播变量为例(引用[2]间接涉及),重建时driver需要重新分发GB级数据到上百个节点;Executor重建(引用[4]的应用标识机制)涉及YARN/K8s的资源调度开销,可能达分钟级。用户体验的影响容易被忽略,其实spark-shell重启(引用[3]的REPL示例)会导致加载的外部jar包失效,这对调试效率影响很大。而SQL临时表丢失(引用[5]的shuffle分区参数相关)会让复杂查询前功尽弃。最后给出的建议侧重可操作性:如果是环境切换(如local转集群),明确推荐spark-submit;针对配置修改场景,要提醒用户优先用SparkConf.set动态调整而非重建。单元测试的例子特别实用,因为测试套件里频繁初始化SparkContext是常见需求。用户可能还想知道:能否强制销毁旧实例?虽然没在资料里看到,但凭经验知道sc.stop()后可以新建,只是中间会有资源回收延迟。另外动态调整的边界条件需要补充说明,比如修改shuffle分区数(引用[5])是可以动态生效的典型例子。</think> 基于提供的参考资料,Spark重新初始化(通常指重建`SparkContext`或`SparkSession`)可能导致以下影响和结果: --- ### **1. 资源重复开销** - **驱动端资源浪费** 重新初始化会创建新的SparkContext,导致Driver进程中的元数据管理、DAG调度器、任务调度器等核心组件重复加载,增加内存和CPU开销[^2][^4]。 - **Executor资源泄漏风险** 若未正确停止旧SparkContext,其关联的Executor可能残留在集群中,占用YARN/Mesos/K8s资源[^1][^4]。 --- ### **2. 任务执行中断** - **作业强制终止** 旧SparkContext上运行的任务会被强制终止(如未完成的Shuffle、缓存计算丢失),导致数据不一致或部分计算结果丢失[^1][^4]。 - **RDD/DataFrame失效** 所有通过旧Context创建的RDD/DataFrame将不可用(如执行操作会报`NullPointerException`或`ContextStoppedException`)[^2][^4]。 --- ### **3. 应用标识(Application ID)变更** - **监控与日志断层** 新SparkContext会生成**新的Application ID**(如YARN模式从`application_xxx_001`变为`application_xxx_002`),导致Spark UI监控历史中断、日志无法关联[^4]。 - **资源管理器混淆** YARN/Mesos可能误判为两个独立应用,造成资源调度冲突[^4]。 --- ### **4. 配置与状态丢失** - **配置重置** 自定义配置(如`spark.sql.shuffle.partitions`)需重新设定,临时表(`registerTempTable`)和UDF注册信息会清空[^2][^5]。 - **广播变量失效** 原有广播变量(`Broadcast Variables`)需重新创建并分发,增加网络开销[^2]。 --- ### **5. 端口与锁冲突** - **端口绑定失败** Driver端占用的端口(如4040/4041用于UI,随机端口用于RPC)若未及时释放,新Context会因端口冲突启动失败(报`BindException`)[^1][^4]。 - **文件锁冲突** 本地模式下可能因临时目录锁(如`/tmp`)导致初始化报错[^4]。 --- ### **最佳实践建议** 1. **避免运行时重建** 优先使用`spark-submit`重启应用而非代码内重建Context(引用[3])。 2. **动态配置更新** 利用`spark.conf.set()`动态修改参数(如`spark.sql.shuffle.partitions`),而非重建Context[^5]。 3. **安全销毁旧实例** 若必须重建,先调用`sc.stop()`确保旧Context彻底关闭,释放端口和Executor资源[^1][^2]。 ```scala // 正确重建示例 val oldSc = SparkContext.getOrCreate() oldSc.stop() // 释放资源 // 创建新Context val newConf = new SparkConf().setAppName("newApp").setMaster("local[*]") val newSc = new SparkContext(newConf) ``` --- ### 相关问题 1. SparkContext停止(`sc.stop()`)后哪些资源会被释放? 2. 如何在保持Application ID不变的情况下更新Spark配置? 3. Spark Streaming中重启`StreamingContext`会导致哪些数据丢失? 4. 如何避免Spark应用因端口冲突启动失败? [^1]: SparkContext初始化涉及底层端口绑定和资源调度(引用1)。 [^2]: SparkContext是Spark功能的唯一入口(引用2)。 [^3]: master参数应通过spark-submit传递(引用3)。 [^4]: 重建会导致Application ID变更和资源泄漏(引用4)。 [^5]: 动态配置可替代重建Context(引用5)。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值