大数据(8y)Spark3.0内核

Spark 内存管理-内存划分 专栏原创出处:github-源笔记文件 ,github-源码 ,欢迎 Star,转载请附上原文出处链接和本声明。 文章目录1、前言2、堆内存和堆外内存3、内存划分3.1 相关参数3.2 内存划分示意图4、相关源码解读4.1 UnrollMemory 理解参考 1、前言 spark 内存管理源码说明 spark-core jar 中 org.apache.spark.memory 负责内存管... 阅读详情

1、Spark On YARN 部署模式的运行机制

  1. 任务提交后,启动Driver;
  2. Driver向集群管理器注册应用程序;
  3. 集群管理器根据此任务的配置文件分配Executor并启动;
  4. Driver执行main函数,跑到行动算子时就反向推算,按宽依赖划分Stage,每一个Stage对应一个TaskSet,TaskSet中有多个Task,查找可用资源Executor进行调度;
  5. 根据本地化原则,Task会被分发到指定的Executor去执行,在任务执行的过程中,Executor也会不断与Driver进行通信,报告任务运行情况。

1.1、Spark On YARN Cluster

spark-submit \
--master yarn \
--deploy-mode cluster \
--class org.apache.spark.examples.SparkPi \
$SPARK_HOME/examples/jars/spark-examples_2.12-3.0.0.jar \
999

提交Spark任务,并配置--master yarn和--deploy-mode cluster,然后查看Java进程
在这里插入图片描述

1.2、Spark On YARN Client

spark-submit \
--master yarn \
--class org.apache.spark.examples.SparkPi \
$SPARK_HOME/examples/jars/spark-examples_2.12-3.0.0.jar \
999

提交Spark任务,并配置--master yarn,然后查看Java进程

2、任务调度机制

  1. Job是以行动算子为界
  2. Stage是Job的子集,以RDD宽依赖为界
  3. Task是Stage的子集, 分 区 数 = T a s k 数 量 分区数=Task数量 分区数=Task数量
  • Stage级调度(DAGScheduler)
    DAGScheduler负责Stage级的调度,主要是将Job切分成若干Stages,并将每个Stage打包成TaskSet交给TaskScheduler调度

  • Task级调度(TaskScheduler)
    TaskScheduler负责Task级的调度,将TaskSet按照指定的调度策略分发到Executor上执行
    调度过程中SchedulerBackend负责提供可用资源

源码解析简化图

3、Shuffle机制

在划分stage时
最后一个stage为ResultStage
前面的stage为ShuffleMapStage,其结束伴随shuffle

sort-based shuffle流程简化图

1、写入内存缓冲
2、缓冲满后,溢写到临时文件
3、所有临时文件合并成一个数据文件,并创建一个索引文件
4、一个MapTask生成一个数据文件和一个索引文件
5、sort-based shuffle生成文件总数:MapTask数量 x 2
6、ReduceTask根据索引文件从数据文件读取数据

4、内存管理

堆内(On-heap)和堆外(Off-heap)内存

Executor的内存管理建立在JVM的内存管理之上
Spark引入了堆外内存,使之可以直接在工作节点的系统内存中开辟空间来使用

内存空间分配

动态占用机制

5、并行度

  • 并行度:所有Executor可以同时执行的Task数量
  • 每个Executor的一个Core同时只能执行一个Task
  • 最 大 并 行 度 = E x e c u t o r 数 量 × 每 个 E x e c u t o r 的 C o r e 数 量 最大并行度 = Executor数量 \times 每个Executor的Core数量 最大并行度=Executor数量×每个Executor的Core数量
spark-submit \
--class a.b.c.PageViewPreHour \
--master yarn
--deploy-mode cluster
--driver-memory 8g \
--num-executors 40 \
--executor-memory 10g \
--executor-cores 2 \
/home/yellow/spark_jar/real_time.jar \
spark-submit参数参数值说明
--driver-memory8gDriver内存
--num-executors40Executor数量
--executor-memory10g每个Executor的内存大小
--executor-cores2每个Executor的CPU core数量
  • E x e c u t o r 总 内 存 = E x e c u t o r 数 量 × 每 个 E x e c u t o r 内 存 = 400 G Executor总内存 = Executor数量 \times 每个Executor内存 = 400G Executor总内存=Executor数量×每个Executor内存=400G
    E x e c u t o r 总 核 心 数 = E x e c u t o r 数 量 × 每 个 E x e c u t o r 核 心 数 = 80 Executor总核心数 = Executor数量 \times 每个Executor核心数 = 80 Executor总核心数=Executor数量×每个Executor核心数=80
    核心数与内存(G)配比 1 : 5 1:5 1:5

  • 最 大 并 行 度 = E x e c u t o r 总 核 心 数 = 80 最大并行度 = Executor总核心数 = 80 最大并行度=Executor总核心数=80
    如果RDD有160个分区(一个分区对应一个Task),就需要两轮计算
    如果RDD有50个分区,那么计算时只用了50个Core,其余30个Core空转(资源浪费)

  • 并行度调优
    并行度过高会导致资源浪费,并行度过低会导致效率低下
    通常建议 总核数设置为Task数量的 1 2 \frac{1}{2} 21​或 1 3 \frac{1}{3} 31​
    没有推荐 1 : 1 1:1 1:1,是因为有的Task快 有的Task慢,快的Task完成后会造成Core空闲
    不过,在实时计算的场景下,可设成 1 : 1 1:1 1:1,这样效率高

6、附录

6.1、相关单词

en🔉cn
RPCRemote Procedure Call远程过程调用
spillspɪlv. (使)溢出;n. 溢出液
evictionɪˈvɪkʃnn. 逐出;收回

6.2、源码截取

查看源码需要先导入依赖并下载对应源码

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-yarn_2.12</artifactId>
    <version>3.0.0</version>
</dependency>

6.2.1、SparkOnYARNCluster

spark-submit --master yarn --deploy-mode cluster …

-----------------------------------
第一部分: 客户端和YARN通信

org.apache.spark.deploy.SparkSubmit.main
    -- submit.doSubmit(args)
        --super.doSubmit(args)
            // 解析spark-submit后传入的参数,加载spark默认的参数
            -- val appArgs = parseArguments(args)  
            --submit(appArgs, uninitLog)
                --doRunMain()
                //运行spark-submit 提交的主类 中的main方法
                    --runMain(args, uninitLog)
                    
                    // 如果deployMode == CLIENT,此时childMainClass=自己提交的全类名
                    // 如果deployMode == CLUSTER,是YARN集群 childMainClass=org.apache.spark.deploy.yarn.YarnClusterApplication
                        --val (childArgs, childClasspath, sparkConf, childMainClass) = prepareSubmitEnvironment(args)
                        
                        //创建childMainClass的Class类型
                        --mainClass = Utils.classForName(childMainClass)
                        
                         --val app: SparkApplication = if (classOf[SparkApplication].isAssignableFrom(mainClass)) {
                           //如果是cluster 模式,此时运行下一行
                           mainClass.getConstructor().newInstance().asInstanceOf[SparkApplication]
                           } else {
                             new JavaMainApplication(mainClass)
                           }
                            
                         -- app.start(childArgs.toArray, sparkConf)
                         
                         // YarnClusterApplication.start()  Client是可以和yarn进行通信的一个客户端
                            --new Client(new ClientArguments(args), conf, null).run()
                                --this.appId = submitApplication()
                                
                                    // 提交应用程序到YARN上,获取YARN的返回值
                                    -- val newApp = yarnClient.createApplication()
                                    
                                    //确定app保存临时数据的作业目录,通常是在hdfs中的/tmp目录中生成一个子目录
                                    -- val appStagingBaseDir = sparkConf.get(STAGING_DIR)
                                    
                                    //确保YARN有足够的资源运行当前app的AM
                                    //当集群资源不足时就会阻塞,塞到超时就会FAILD
                                    -- verifyClusterResources(newAppResponse)

                                    --  val containerContext = createContainerLaunchContext(newAppResponse)

                                        //AM是YARN提供的一个接口
                                        //任何的应用程序如果希望提交APP到YARN,实现AM的接口
                                        //  MR写的app就由MR实现AM
                                        //  Spark写的App就由Spark实现AM
                                        --val amClass =
                                          if (isClusterMode) {
                                                //集群模式AM的全类名是org.apache.spark.deploy.yarn.ApplicationMaster
                                            Utils.classForName("org.apache.spark.deploy.yarn.ApplicationMaster").getName
                                          } else {
                                            Utils.classForName("org.apache.spark.deploy.yarn.ExecutorLauncher").getName
                                          }
                                    --  val appContext = createApplicationSubmissionContext(newApp, containerContext)
                                    
                                    //提交运行AM
                                    --  yarnClient.submitApplication(appContext)
                                    
----------------------------------------
第二部分  AM启动
    ApplicationMaster.main    
      --master.run()
        --if (isClusterMode) {
            //如果是Cluster模式就在AM中运行Driver
            --runDriver()
          } else {
            runExecutorLauncher()
          }
          
          // 启动一个线程,运行用户自己编写的app应用程序的main方法
          --userClassThread = startUserApplication()
          
          //等待用户自己编写的app的main方法运行结束后,获取用户自己创建的SparkContext
          --val sc = ThreadUtils.awaitResult(sparkContextPromise.future,
                    Duration(totalWaitTime, TimeUnit.MILLISECONDS))
          
          // 向RM回报,AM已经启动成功了
           --registerAM(host, port, userConf, sc.ui.map(_.webUrl), appAttemptId)
          
          // 创建一个可以向RM申请资源的对象,申请资源启动Executor
          -- createAllocator(driverRef, userConf, rpcEnv, appAttemptId, distCacheConf)
          
            //allocator: YarnAllocator 作用就是向RM申请Container,决定获取到COntainer后,使用Container干什么
            --allocator = client.createAllocator()
            
            --allocator.allocateResources()
                //发送申请请求
                -- val allocateResponse = amClient.allocate(progressIndicator)
                
                //从YARN的响应中获取已经分配的Container
                --val allocatedContainers = allocateResponse.getAllocatedContainers()
                
                //处理申请到的Container
                -- handleAllocatedContainers(allocatedContainers.asScala)
                
                    //在Container中运行进程
                    -- runAllocatedContainers(containersToUse)
                    
                        //每个Container都会创建一个ExecutorRunnable,交给线程池运行
                        --new ExecutorRunnable.run
                        
                            -- nmClient = NMClient.createNMClient()
                                nmClient.init(conf)
                                nmClient.start()
                                
                                //准备容器中的启动进程
                                startContainer()
                                  --org.apache.spark.executor.YarnCoarseGrainedExecutorBackend 容器中启动的进程
                                    --val commands = prepareCommand()

6.2.2、SparkOnYARNClient

spark-submit --master yarn …

-----------------------------------
第一部分: 客户端和YARN通信

org.apache.spark.deploy.SparkSubmit.main
    -- submit.doSubmit(args)
        --super.doSubmit(args)
            // 解析spark-submit后传入的参数,加载spark默认的参数
            -- val appArgs = parseArguments(args)  
            --submit(appArgs, uninitLog)
                --doRunMain()
                //运行spark-submit 提交的主类 中的main方法
                    --runMain(args, uninitLog)
                    
                    // 如果deployMode == CLIENT,此时childMainClass=自己提交的全类名
                    // 如果deployMode == CLUSTER,是YARN集群  childMainClass=org.apache.spark.deploy.yarn.YarnClusterApplication
                        --val (childArgs, childClasspath, sparkConf, childMainClass) = prepareSubmitEnvironment(args)
                        
                        //创建childMainClass的Class类型
                        --mainClass = Utils.classForName(childMainClass)
                        
                         --val app: SparkApplication = if (classOf[SparkApplication].isAssignableFrom(mainClass)) {
                               mainClass.getConstructor().newInstance().asInstanceOf[SparkApplication]
                               } else {
                               //如果是client 模式,此时运行下一行
                               new JavaMainApplication(mainClass)
                            }
                            
                            //JavaMainApplication.start
                         -- app.start(childArgs.toArray, sparkConf)
                         
                            //获取用户编写的 app类的main
                            --  val mainMethod = klass.getMethod("main", new Array[String](0).getClass)
                            
                            //执行main方法,Driver启动
                            --mainMethod.invoke(null, args)
                            
------------------------------------------------------------------------
第二部分: WordCount.main

  SparkContext sc=new SparkContext
  
  SparkContext的重要组件:
          private var _taskScheduler: TaskScheduler = _   //负责Task的调度
          
          private var _dagScheduler: DAGScheduler = _   // Job中DAG Stage的切分
          
          private var _env: SparkEnv = _ //  RpcEnv(通信环境) BlockManager(存数据)
          
          
--------------
_taskScheduler = ts
    _taskScheduler.start()
        //YarnClientSchedulerBackend.start()
        --backend.start()
            --   client = new Client(args, conf, sc.env.rpcEnv)
            
            //提交应用程序到YARN
            --   bindToYarn(client.submitApplication(), None)
            
            //参考cluster模式
            ...
            
            --在容器中运行的AM的全类名: org.apache.spark.deploy.yarn.ExecutorLauncher
            
-----------------------------
第二部分:启动AM 
 org.apache.spark.deploy.yarn.ExecutorLauncher.main
          //ExecutorLauncher 是对AM的封装,也是AM的实现
         ApplicationMaster.main(args)
            -- --master.run()
               if (isClusterMode) {
                   
                    --runDriver()
                  } else {
                    //client模式运行
                    runExecutorLauncher()   //申请Container启动Executor
                  }

----------------------------------------------------------------------------
                         
                         // YarnClusterApplication.start()  Client是可以和yarn进行通信的一个客户端
                            --new Client(new ClientArguments(args), conf, null).run()
                                --this.appId = submitApplication()
                                
                                    // 提交应用程序到YARN上,获取YARN的返回值
                                    -- val newApp = yarnClient.createApplication()
                                    
                                    //确定app保存临时数据的作业目录,通常是在hdfs中的/tmp目录中生成一个子目录
                                    -- val appStagingBaseDir = sparkConf.get(STAGING_DIR)
                                    
                                    //确保YARN有足够的资源运行当前app的 AM
                                    // 如果集群资源不足,此时会阻塞,一直阻塞到超时,会FAILD
                                    -- verifyClusterResources(newAppResponse)
                                    
                                    --  val containerContext = createContainerLaunchContext(newAppResponse)
                                    
                                        // 确定AM的主类名
                                        // AM是YARN提供的一个接口
                                        // 任何的应用程序如果希望提交APP到YARN,实现AM的接口
                                        //  MR写的app,MR实现AM
                                        //  spark写的App,spark实现AM
                                        --val amClass =
                                          if (isClusterMode) {
                                                //集群模式AM的全类名是org.apache.spark.deploy.yarn.ApplicationMaster
                                            Utils.classForName("org.apache.spark.deploy.yarn.ApplicationMaster").getName
                                          } else {
                                            Utils.classForName("org.apache.spark.deploy.yarn.ExecutorLauncher").getName
                                          }
                                    --  val appContext = createApplicationSubmissionContext(newApp, containerContext)
                                    
                                    //提交运行AM
                                    --  yarnClient.submitApplication(appContext)

6.2.3、Executor启动之反向注册

org.apache.spark.executor.YarnCoarseGrainedExecutorBackend 本身就是一个通信端点
    //RpcEndpointRef:某个通信端点的引用
    var driver: Option[RpcEndpointRef] = None

------------------
第一部分: YarnCoarseGrainedExecutorBackend进程启动
--YarnCoarseGrainedExecutorBackend.main
    -- CoarseGrainedExecutorBackend.run(backendArgs, createFn)
    
          //向Driver请求spark的配置信息
          --val executorConf = new SparkConf
          
          // 当前进程在网络中有一个通信的别名称为Executor
         -- env.rpcEnv.setupEndpoint("Executor",
           backendCreateFn(env.rpcEnv, arguments, env, cfg.resourceProfile))
          
          //阻塞,一直运行,除非Driver发送停止命令
          --env.rpcEnv.awaitTermination()

constructor -> onStart -> receive* -> onStop
--------------------------------------
第二部分: YarnCoarseGrainedExecutorBackend进程向Driver发送注册请求
onStart
     // ref:RpcEndpointRef   代表Driver的通信端点引用(电话号)
     // 向Driver发RegisterExecutor消息,请求答复一个Boolean的值
    -- ref.ask[Boolean](RegisterExecutor(executorId, self, hostname, cores, extractLogUrls,
         extractAttributes, _resources, resourceProfile.id))
       }(ThreadUtils.sameThread).onComplete {
         case Success(_) =>
           //成功,自己给自己发 RegisteredExecutor消息
           self.send(RegisteredExecutor)
           //失败,进程就退出
         case Failure(e) =>
           exitExecutor(1, s"Cannot register with driver: $driverUrl", e, notifyDriver = false)

-------------------------------------
第三部分: Driver处理注册请求
    DriverEndPoint.receiveAndReply
        --case RegisterExecutor
            // 判断是否已经注册过了,如果注册过了,回复失败;判断是否拉黑,拉黑,注册失败
            // 否则注册,注册完成后,回复true
            context.reply(true)

----------------------------------------
第四部分: YarnCoarseGrainedExecutorBackend 注册成功后

YarnCoarseGrainedExecutorBackend.receive
    -- case RegisteredExecutor =>
         logInfo("Successfully registered with driver")
         try {
           // Spark的计算者,维护了一个线程池,用来计算各种Task
           executor = new Executor(executorId, hostname, env, userClassPath, isLocal = false,
           resources = _resources)
          
          // 给Driver发LaunchedExecutor消息
          driver.get.send(LaunchedExecutor(executorId))

-----------------------------------------------------
第五部分: Driver处理LaunchedExecutor请求
     DriverEndPoint.receive
        -- case LaunchedExecutor(executorId) =>
            executorDataMap.get(executorId).foreach { data =>
              data.freeCores = data.totalCores
        }
        //Driver向Executor发送工作任务(Task)
        makeOffers(executorId)
                //从调度池中,根据TaskSet的优先级,调度其中的Task。
                // 按照轮流发送的原则将Task调度到哦所有的Executor,保证负载均衡。
                //调度应该发往次Executor的Task
            --scheduler.resourceOffers(workOffers)
            
                -- launchTasks(taskDescs)
                    -- val serializedTask = TaskDescription.encode(task)
                    
                    //为要发送的Executor打个招呼,发送Task  
                    --executorData.executorEndpoint.send(LaunchTask(new SerializableBuffer(serializedTask)))

--------------------------------------------------
第六部分: Executor收到Task
    -- case LaunchTask(data) =>
      if (executor == null) {
        exitExecutor(1, "Received LaunchTask command but executor was null")
      } else {
      // 反序列化得到Task的描述(TaskDescription)
        val taskDesc = TaskDescription.decode(data.value)
        logInfo("Got assigned task " + taskDesc.taskId)
        taskResources(taskDesc.taskId) = taskDesc.resources
        
        //启动Task的运算
        executor.launchTask(this, taskDesc)
        
            //创建一个Task运行的线程
            -- val tr = new TaskRunner(context, taskDescription)
                runningTasks.put(taskDescription.taskId, tr)
                
                // 启动线程
                threadPool.execute(tr)
                
                    --TaskRunner.run()
                        //构造可以运行的Task对象
                        --task = ser.deserialize[Task[Any]]
                        
                        //运行Task获取结果
                        -- val res = task.run()
                            
                            // ShuffleMapTask  或  ResultTask
                            --runTask(context)
      }

6.2.4、任务调度

--------------
RDD.collect
    --val results = sc.runJob(this, (iter: Iterator[T]) => iter.toArray)
    
    //判断是否存在闭包,闭包变量是否可以序列化
    -- val cleanedFunc = clean(func)
    
    -- dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, resultHandler, localProperties.get)
    
    -- val waiter = submitJob(rdd, func, partitions, callSite, resultHandler, properties)
    
        // event处理循环,放入一个事件 JobSubmitted  
        //  eventProcessLoop = new DAGSchedulerEventProcessLoop
        -- eventProcessLoop.post(JobSubmitted())
            --EventLoop.onReceive(event)
                -- doOnReceive(event)
                    --case JobSubmitted(jobId, rdd, func, partitions, callSite, listener, properties) =>
                        dagScheduler.handleJobSubmitted(jobId, rdd, func, partitions, callSite, listener, properties)
                        
----------------------
 dagScheduler.handleJobSubmitted
       // Job的最后一个阶段
      --var finalStage: ResultStage = null
      
      -- finalStage = createResultStage(finalRDD, func, partitions, jobId, callSite)
      
        //递归依次从后往前找,将ResultStage的所有祖先ShuffleMapStage都创建完毕,最后才创建最后一个Stage
        --val parents = getOrCreateParentStages(rdd, jobId)
        
        --val stage = new ResultStage(id, rdd, func, partitions, parents, jobId, callSite)
        
        // ResultStage创建完毕后,才会生成Job
        -- val job = new ActiveJob(jobId, finalStage, callSite, listener, properties)
        
        //提交ResultStage
        --submitStage(finalStage)
        
            //查看当前阶段有没有未提交的父阶段,按照父阶段的ID排序
            --val missing = getMissingParentStages(stage).sortBy(_.id)
            
                //如果父阶段未提交,按照顺序依次提交,最后提交自己
                --if (missing.isEmpty) {
                    logInfo("Submitting " + stage + " (" + stage.rdd + "), which has no missing parents")
                      submitMissingTasks(stage, jobId.get)
                  } else {
                    for (parent <- missing) {
                      submitStage(parent)
                    }
                    waitingStages += stage
                  }
                
                    // 根据Stage类型创建对应的Task,创建时,根据当前Stage要计算的分区数确定
                    // 如何知道每一个Stage要计算的partition的数量?取决于Stage最后一个RDD的分区数
                    --val tasks: Seq[Task[_]] = try {
                          val serializedTaskMetrics = closureSerializer.serialize(stage.latestInfo.taskMetrics).array()
                          stage match {
                            case stage: ShuffleMapStage =>
                              stage.pendingPartitions.clear()
                              partitionsToCompute.map { id =>
                                val locs = taskIdToLocations(id)
                                val part = partitions(id)
                                stage.pendingPartitions += id
                                new ShuffleMapTask(stage.id, stage.latestInfo.attemptNumber,
                                  taskBinary, part, locs, properties, serializedTaskMetrics, Option(jobId),
                                  Option(sc.applicationId), sc.applicationAttemptId, stage.rdd.isBarrier())
                              }

                            case stage: ResultStage =>
                              partitionsToCompute.map { id =>
                                val p: Int = stage.partitions(id)
                                val part = partitions(p)
                                val locs = taskIdToLocations(id)
                                new ResultTask(stage.id, stage.latestInfo.attemptNumber,
                                  taskBinary, part, locs, id, properties, serializedTaskMetrics,
                                  Option(jobId), Option(sc.applicationId), sc.applicationAttemptId,
                                  stage.rdd.isBarrier())
                              }
                          }
                          
                    //将每个Stage的task放入调度池,通知Driver去调度
                    //TaskSet:包含了一个Stage所有的Tasks, 一个Task的集合
                    --taskScheduler.submitTasks(new TaskSet(
                        tasks.toArray, stage.id, stage.latestInfo.attemptNumber, jobId, properties))
                        
                        //TaskSetManager: 追踪每一个TaskSet中所有Task的运行情况,在它们失败时重启。通过延迟调度
                        //处理位置敏感的调度,调度每个Task
                           --val manager = createTaskSetManager(taskSet, maxTaskFailures)
                           
                           //将TaskSetManager加入调度池(FIFO | FAIR),不同的调度池,会决定不同的TaskSet被调度的优先级
                           -- schedulableBuilder.addTaskSetManager(manager, manager.taskSet.properties)
                           
                           -- backend.reviveOffers()
                            //给Driver发消息,告诉Driver有新的TaskSetManager入池了,可以开始发送了
                            -- driverEndpoint.send(ReviveOffers)
                                -- case ReviveOffers =>
                                                makeOffers()
慕课网实战项目《WebAPP书城整站开发》笔记一:底部边栏样式实现 推荐IMOOC实践课程: 《WebAPP 书城整站开发》 阅读器底部边栏样式实现 阅读详情

相关推荐

大数据学习23:Spark:大数据的计算引擎(Scala开发环境安装)

第一部分:Scala编程语言 第二部分:Spark Core内核(最重要的内容)—> 概念RDD:相当于MapReduce 第三部分:Spark SQL:相当于Hive,也支持SQL语句 -----> 底层依赖Spark Core ----> 依赖RDD 第四部分:Spark Streaming:相当于Storm用于流式计算 - ----> 底层依赖Spark Core -...

weixin_44804248的博客 323

Spark 统一内存管理模型详解

前提 从spark3.0开始没有静态管理了,只有个统一内存管理 onHeap:java虚拟机管理的内存是堆内内存 offHeap:java虚拟机管理之外的内存,系统内存是堆外内存 堆内内存(on-heap memory) Execution 内存:主要用于存放 Shuffle、Join、Sort、Aggregation 等计算过程中的临时数据 Storage 内存:主要用于存储 spark 的 cache 数据,例如RDD的缓存、unroll数据; 用户内存(User Memory):主

qq_24186017的博客 490

Qwen 3.6生产级兼容性测试:Spark+Halo+CUDA/HIP全栈验证

大模型落地本质是系统工程,而非单点推理——核心在于能否无缝融入企业现有大数据栈与异构算力底座。Qwen作为主流开源大模型,其工程价值取决于在Spark数据流水线中的特征提取稳定性、在Halo等轻量分布式框架下的微调可扩展性,以及对CUDA/HIP双生态、多版本(11.0–13.2)、多硬件(A100/MI250X/T4)的真实兼容能力。本文基于TB级日志处理、酒店智能推荐、空气质量时序预测等典型场景,揭示Qwen 3.6在数据搬运、算子融合、显存复用与跨设备通信四大承压断面的表现,为算法工程师、MLOps团

weixin_33857230的博客 413

搞懂 Spark 系列之深入理解Spark内存管理

本文详细介绍了Spark内存管理,包括Spark内存概述、内存管理机制及底层源码,欢迎交流讨论!

一入大数据深似海?别怕!“数据极客圈”就是你的救生圈,走对圈子跟对人,趣析数据、畅聊趋势,快进圈子! 4619

Hadoop+Spark 大数据分析(一)之 虚拟机安装及Java环境的配置

系统与平台 文章目录 目录 系统与平台 文章目录 前言 一、系统环境 二、系统设计 1.主机分配 2.功能分配 三、 环境准备 1.安装虚拟机 ​ 2.配置Java环境 说明 环境监察 安装JDK ​ 配置JDK ​ ​ ​ 3.配置网络参数 设置主机名 配置 hosts 文件 配置静态IP 禁用防火墙 四、集群环境搭建 1.下载 hadoop 总结 前言 为了学习大数据下的数据分析,第一次尝试搭建完全分布式的...

kyle6666的博客 893

Amazon EMR实战指南:Spark云原生调优与成本治理

Apache Spark作为主流大数据计算引擎,其在云环境的稳定运行高度依赖底层资源调度与存储协同。Amazon EMR并非简单托管Hadoop,而是深度集成S3数据湖、YARN资源管理与Spot实例弹性的云原生大数据操作系统。它通过预调优JVM参数、S3A提交协议、跨AZ容错及Instance Fleet智能编排,显著降低Spark on Cloud的运维复杂度。技术价值体现在分钟级弹性伸缩、断点续训高可用、细粒度权限管控与按秒计费成本优化。典型应用于电商实时特征计算、金融风控ETL流水线及IoT时序数据

weixin_30256901的博客 340

spark-3.0.1源码阅读之内存管理

spark-3.0.1源码阅读之内存管理1 内存管理的由来1.1 shuffle需要1.2 cpu的瓶颈2 内存管理解析2.1 管理谁的内存2.2 内存管理的顶层设计2.3 内存管理的实现3 源码参照3.1 计算区3.2 存储区4 总结   Spark的内存管理比较庞大,内部分类也比较细致,所以对这部分的理解最重要的就是要弄清楚这些庞大又细致的设计和实现的来龙去脉,它们从哪里来,要实现什么目的,是怎样实现的问题.   如果弄明白了上述这些问题,再回过头来看源码就一目了然了,甚至是只看类名或方法名就能猜到其

qq_33570700的博客 551

Ambari 3.0+BigTop 3.3集群部署实战

Ambari 3.0+BigTop 3.3集群部署

docsz的博客 614

Spark3.0新特性-AQE

想要更全面了解Spark内核和应用实战,可以购买我的新书。 《图解Spark 大数据快速分析实战》(王磊)【摘要 书评 试读】- 京东图书https://item.jd.com/13613302.html AQE 1.AQE的概念 Spark SQL是Spark开发中使用最广泛的引擎,它使得我们通过简单的几条SQL语句就能完成海量数据(TB或PB级数据)的分析。 AQE(Adaptive Query Execution,自适应查询执行)的作用是对正在执行的查询任务进行优化。AQE使Spark计划.

wangleigiser的博客 4357

Linux环境下Spark安装与配置完整资源包

简介:Spark是IT行业中广泛使用的大数据处理框架,适用于大规模数据处理、机器学习和实时分析等场景。本文提供在Linux系统上安装与配置Spark的全套指导,涵盖Java环境准备、Spark下载解压、环境变量设置、Hadoop兼容性配置、服务启停及示例运行等全过程。该资源包经过实际验证,帮助开发者快速搭建Spark开发环境,顺利开展后续大数据应用开发与测试工作。

weixin_32999557的博客 786

远程桌面报‘数据加密错误‘?可能是网卡设置惹的祸(附TCP校验关闭教程)

本文深入分析远程桌面连接中出现的'数据加密错误'问题,指出网卡设置可能是根本原因,并提供详细的TCP校验关闭教程。通过禁用网卡高级属性中的'TCP校验和IPv4'与'IPv4承载卸载'功能,可有效解决RDP协议与硬件加速的兼容性问题,适用于Windows和Linux系统。

view3的博客 280

spark2.0 on mesos1.0.1

最近接触到大数据,帮同事搭建环境。因都是最新版本,中间参考过好多博客,被坑的不要不要的。现将我的部署总结下,供大家参考。 我准备了8台服务器,做的集群。服务器全是阿里云的ecs,系统版本centos6.5 64位,spark2.0 mesos1.0.1 服务器命名规则M00001,M00002....M00008,其中M00001作为mesos的master节点,其他都是slave节点。

qn0007的博客 1061

内网环境下的高德地图离线化实战:从瓦片下载到交互功能集成

本文详细介绍了在内网环境中部署离线高德地图的完整实战方案。针对军工、能源、金融等对网络隔离与数据安全有严格要求的场景,文章核心解决了离线地图的两大基石:地图瓦片数据的高效下载与本地化,以及高德地图JS API的获取与插件集成。通过具体代码示例,进一步讲解了如何实现地图初始化、海量点标注与聚合、自定义图标及框选查询等核心交互功能,并分享了内网部署的路径配置、性能优化及法律合规等关键注意事项,为开发者在封闭网络环境下构建稳定、可控的地图应用提供了清晰指南。

Apple的专栏 395

Spark星火发射平台:一站式本地化大数据开发测试环境部署与实战

大数据处理的核心在于高效、可扩展的数据计算框架,Apache Spark作为其中的主流选择,通过内存计算和DAG调度引擎显著提升了批处理与流式任务的性能。其技术价值在于将复杂的数据处理逻辑抽象为简单的API,并支持SQL查询、机器学习和图计算等多种范式,极大地降低了分布式计算的开发门槛。在实际应用中,Spark广泛用于ETL、实时分析、数据湖查询等场景,但环境搭建、集群配置和资源管理往往是开发者面临的首要挑战。为了解决这些痛点,本地化的一站式部署平台应运而生,它们通过预集成环境、提供Web UI和REST

weixin_34221773的博客 364

新能源场站必看:一次调频与AGC/AVC的协同控制逻辑解析(含典型拓扑图)

本文深度解析了新能源场站中一次调频与AGC/AVC的协同控制逻辑。针对电网频率与电压稳定需求,详细阐述了三者在响应时序、控制目标上的分工与配合,并重点剖析了以RCL-0923装置为核心的指令融合架构与典型拓扑,为场站实现高效、稳定的协同运行提供了清晰的实践指导。

brown的博客 1068

已解决“TimeouEror [WinEror 10060由于连接方在一段时间后没有正确答复 或连接的主机没有反应,连接尝试失败“,亲测有效!!!

已解决"TimeouEror [WinEror 10060由于连接方在一段时间后没有正确答复 或连接的主机没有反应,连接尝试失败",亲测有效!!!

wbajsjhhhhh的博客 1万+

spark单机版本搭建

spark环境快速搭建

flying roc 374

yolov26改进 | 融合改进篇 | 基于 MobileNetV4 和双向特征金字塔网络BiFPN的融合改进(全网独家首发)

本文介绍BiFPN与MobileNetV4融合改进的YOLOv26。许多模块单独使用能够涨点,但直接叠加后可能因功能重复、通道不匹配、尺度冲突而掉点,因此融合前必须理解各模块作用。MobileNetV4利用UIB与Mobile MQA构建轻量主干,提升特征提取能力;BiFPN通过可学习权重完成双向多尺度融合,强化大、中、小目标的信息交互。两者优化Backbone与Neck,功能互补、结构冲突较少。本文提供代码、配置、消融对比及Codex修改思路,MobileNetV4也可替换其他主干,便于组合实验与二次创新

Snu77的博客 244

大数据系列第六课:Spark集群环境搭建

第一阶段:Spark streaming、spark sql、kafka、spark内核原  理(必须有一个大型项目经验); 第二阶段:spark运行的各种环境,各种故障的解决,性能  优化(精通spark内核、运行原理); 第三阶段:流处理、机器学习为鳌头,需要首先掌握前两个  阶段的内容; 跟随王家林老师的零基础讲解,注重动手实战,成为spark高手,笑傲大数据之林! 第一部分:学

kxr0502的博客 1195

【Proteus仿真】点亮小灯系列仿真——小灯闪烁/流水灯/交通灯

本文介绍了基于AT89C51单片机的LED控制案例,共包含5个实例:1)单个LED闪烁;2)共阳极流水灯;3)共阴极流水灯;4)花样流水灯;5)交通灯模拟。每个案例详细说明了电路原理图、接线方式和控制程序实现,其中重点讲解了PWM调光原理及其在LED控制中的应用。案例由简至繁,从基础I/O控制到复杂花样显示,最后实现交通灯逻辑控制,展示了单片机在LED控制中的典型应用方法。文中提供了完整的源代码,便于读者理解和实践。

XU157303764的博客 1884

VMware ESXi 系统里创建虚拟机,虚拟磁盘日志损坏,如何或者把数据备份?

🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

**My Coding Family** 1642

8台DGX Spark集群搭建实战:从网络规划到Kubernetes调度

GPU集群是承载大模型训练与推理的常见基础设施,其核心挑战在于多节点协同与资源调度。DGX Spark作为NVIDIA推出的桌面级AI超级计算机,基于Grace Blackwell平台,提供128GB统一内存,为本地大模型负载提供了高密度算力。当多台设备组成集群时,需理解统一内存、并行策略与通信开销等原理,才能发挥接近1TB内存池的潜力。Kubernetes配合NVIDIA GPU Operator可实现GPU资源的自动化管理与调度,并通过StatefulSet与NCCL验证多节点通信。此类集群适用于大模型

weixin_30613727的博客 426

5、Raspberry Pi CPU架构与多线程编程详解

本文详细介绍了Raspberry Pi的CPU架构(包括ARMv6Z、ARMv7-A和ARMv8-A),通过/proc/cpuinfo解析硬件信息,并深入探讨了多线程编程的核心技术。内容涵盖pthread库的使用,如线程创建、属性设置、等待与分离、线程同步机制(互斥锁),以及实际应用场景如多媒体处理和网络服务。同时强调了线程安全、死锁预防和资源管理等关键注意事项,帮助开发者在Raspberry Pi上构建高效稳定的多线程应用。

sre5engineer的博客 95

Spark算子:RDD常用的10种action算子 & 3种常见保存路径

目录 1. reduce(func) 2. collect() 3. count() 4. first() 5. take(n) 6. takeOrdered(n) 7. aggregate() 8. fold(num)(func) 9. 三种常用RDD元素保存路径 10. countByKey 11. foreach(func)、foreachPartition(func)...

攻城狮Kevin 1621

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

RTX GPU加速Apache Spark:本地化大数据处理实战指南

在大数据处理领域,Apache Spark作为统一的分析引擎,以其内存计算和丰富的API被广泛应用于ETL、机器学习等场景。然而,传统CPU架构在处理计算密集型任务时可能遇到瓶颈。GPU凭借其强大的并行计算能力,通过CUDA核心和加速库,能够将适合并行的计算负载从CPU卸载,从而显著提升数据处理效率。这种技术融合为数据科学家和开发者带来了革命性的价值,使得个人开发者也能在本地环境中高效处理大规模数据。特别是在数据预处理、特征工程和模型训练等场景中,GPU加速能带来数倍的性能提升。本文聚焦于如何利用英伟达RT

cmff98425的博客 326

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Qwen 3.6生产级压测:Spark分布式推理与Halo单机优化实战

大语言模型(LLM)推理在企业生产环境需兼顾兼容性、吞吐与延迟。其核心原理涉及CUDA算子编译、KV Cache内存管理及GPU资源隔离机制。技术价值体现在将Qwen等开源模型无缝嵌入大数据流水线,显著提升结构化数据+AI联合分析效率。典型应用场景包括实时情感分析、客服对话系统、日志智能摘要等OLAP+AI混合负载。本文基于CUDA 12.4与A100硬件,实测Qwen 3.6在Spark分布式推理管道和Halo高性能引擎中的稳定性、吞吐表现与关键避坑配置,覆盖模型加载、RoPE位置编码适配、Rapids

weixin_34409357的博客 895

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

上一篇: 旅游经验总结(不定更)
下一篇: 大数据(5m)ClickHouse极速入门
小基基o_O
博客等级 码龄9年 4414粉丝 467原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小基基o_O

您的鼓励是我创作的巨大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值