DStream 生成 RDD 实例详解

Spark Streaming源码解读之RDD生成全生命周期详解 本篇博客将详细探讨DStream模板下的RDD是如何被创建,然后被执行的。在开始叙述之前,先来思考几个问题,本篇文章也就是基于此问题构建的。 1. RDD是谁产生的? 2. 如何产生RDD? 带着这两个问题开启我们的探索之旅。 一:实战WordCount源码如下:object WordCount { def main(args:Array[String]): Unit ={ 阅读详情

我们在前面的文章讲过,Spark Streaming 的 模块 1 DAG 静态定义 要解决的问题就是如何把计算逻辑描述为一个 RDD DAG 的“模板”,在后面 Job 动态生成的时候,针对每个 batch,都将根据这个“模板”生成一个 RDD DAG 的实例。

image

在 Spark Streaming 里,这个 RDD “模板”对应的具体的类是 DStream,RDD DAG “模板”对应的具体类是 DStreamGraph。

DStream      的全限定名是:org.apache.spark.streaming.dstream.DStream
DStreamGraph 的全限定名是:org.apache.spark.streaming.DStreamGraph

本文我们就来详解 DStream 最主要的功能:为每个 batch 生成 RDD 实例。

Quick Example

我们在前文 DStream, DStreamGraph 详解 中引用了 Spark Streaming 官方的 quick example 的这段对 DStream DAG 的定义,注意看代码中的注释讲解内容:

// ssc.socketTextStream() 将创建一个 SocketInputDStream;这个 InputDStream 的 SocketReceiver 将监听本机 9999 端口
val lines = ssc.socketTextStream("localhost", 9999)

val words = lines.flatMap(_.split(" "))      // DStream transformation
val pairs = words.map(word => (word, 1))     // DStream transformation
val wordCounts = pairs.reduceByKey(_ + _)    // DStream transformation
wordCounts.print()                           // DStream output

这里我们找到 ssc.socketTextStream("localhost", 9999) 的源码实现:

def socketStream[T: ClassTag](hostname: String, port: Int, converter: (InputStream) => Iterator[T], storageLevel: StorageLevel): ReceiverInputDStream[T] = {
  new SocketInputDStream[T](this, hostname, port, converter, storageLevel)
}

也就是 ssc.socketTextStream() 将 new 出来一个 DStream 具体子类 SocketInputDStream 的实例。

然后我们继续找到下一行 lines.flatMap(_.split(" ")) 的源码实现:

def flatMap[U: ClassTag](flatMapFunc: T => Traversable[U]): DStream[U] = ssc.withScope {
  new FlatMappedDStream(this, context.sparkContext.clean(flatMapFunc))
}

也就是 lines.flatMap(_.split(" ")) 将 new 出来一个 DStream 具体子类 FlatMappedDStream 的实例。

后面几行也是如此,所以我们如果用 DStream DAG 图来表示之前那段 quick example 的话,就是这个样子:

也即,我们给出的那段代码,用具体的实现来替换的话,结果如下:

val lines = new SocketInputDStream("localhost", 9999)   // 类型是 SocketInputDStream

val words = new FlatMappedDStream(lines, _.split(" "))  // 类型是 FlatMappedDStream
val pairs = new MappedDStream(words, word => (word, 1)) // 类型是 MappedDStream
val wordCounts = new ShuffledDStream(pairs, _ + _)      // 类型是 ShuffledDStream
new ForeachDStream(wordCounts, cnt => cnt.print())      // 类型是 ForeachDStream

DStream 通过 generatedRDD 管理已生成的 RDD

DStream 内部用一个类型是 HashMap 的变量 generatedRDD 来记录已经生成过的 RDD:

private[streaming] var generatedRDDs = new HashMap[Time, RDD[T]] ()

generatedRDD 的 key 是一个 Time;这个 Time 是与用户指定的 batchDuration 对齐了的时间 —— 如每 15s 生成一个 batch 的话,那么这里的 key 的时间就是 08h:00m:00s,08h:00m:15s 这种,所以其实也就代表是第几个 batch。generatedRDD 的 value 就是 RDD 的实例。

需要注意,每一个不同的 DStream 实例,都有一个自己的 generatedRDD。如在下图中,DStream a, b, c, d各有自己的generatedRDD 变量;图中也示意了 DStream a 的 generatedRDD 变量。

image

DStream 对这个 HashMap 的存取主要是通过 getOrCompute(time: Time) 方法,实现也很简单,就是一个 —— 查表,如果有就直接返回,如果没有就生成了放入表、再返回 —— 的逻辑:

private[streaming] final def getOrCompute(time: Time): Option[RDD[T]] = {
    // 从 generatedRDDs 里 get 一下:如果有 rdd 就返回,没有 rdd 就进行 orElse 下面的 rdd 生成步骤
    generatedRDDs.get(time).orElse {
      // 验证 time 需要是 valid
      if (isTimeValid(time)) {
        // 然后调用 compute(time) 方法获得 rdd 实例,并存入 rddOption 变量
        val rddOption = createRDDWithLocalProperties(time) {
          PairRDDFunctions.disableOutputSpecValidation.withValue(true) {
            compute(time)
          }
        }

        rddOption.foreach { case newRDD =>
          if (storageLevel != StorageLevel.NONE) {
            newRDD.persist(storageLevel)
            logDebug(s"Persisting RDD ${newRDD.id} for time $time to $storageLevel")
          }
          if (checkpointDuration != null && (time - zeroTime).isMultipleOf(checkpointDuration)) {
            newRDD.checkpoint()
            logInfo(s"Marking RDD ${newRDD.id} for time $time for checkpointing")
          }
          // 将刚刚实例化出来的 rddOption 放入 generatedRDDs 对应的 time 位置
          generatedRDDs.put(time, newRDD)
        }
        // 返回刚刚实例化出来的 rddOption
        rddOption
      } else {
        None
      }
    }
  }

最主要还是调用了一个 abstract 的 compute(time) 方法。这个方法用于生成 RDD 实例,生成后被放进 generatedRDD 里供后续的查询和使用。这个 compute(time) 方法在 DStream 类里是 abstract 的,但在每个具体的子类里都提供了实现。

(a) InputDStream 的 compute(time) 实现

InputDStream 是个有很多子类的抽象类,我们看一个具体的子类 FileInputDStream。

// 来自 FileInputDStream
override def compute(validTime: Time): Option[RDD[(K, V)]] = {
    // 通过一个 findNewFiles() 方法,找到 validTime 以后产生的新 file 的数据
    val newFiles = findNewFiles(validTime.milliseconds)
    logInfo("New files at time " + validTime + ":\n" + newFiles.mkString("\n"))
    batchTimeToSelectedFiles += ((validTime, newFiles))
    recentlySelectedFiles ++= newFiles

    // 找到了一些新 file;以新 file 的数组为参数,通过 filesToRDD() 生成单个 RDD 实例 rdds
    val rdds = Some(filesToRDD(newFiles))

    val metadata = Map(
      "files" -> newFiles.toList,
      StreamInputInfo.METADATA_KEY_DESCRIPTION -> newFiles.mkString("\n"))
    val inputInfo = StreamInputInfo(id, 0, metadata)
    ssc.scheduler.inputInfoTracker.reportInfo(validTime, inputInfo)

    // 返回生成的单个 RDD 实例 rdds
    rdds
  }

而 filesToRDD() 实现如下:

// 来自 FileInputDStream
private def filesToRDD(files: Seq[String]): RDD[(K, V)] = {
  // 对每个 file,都 sc.newAPIHadoopFile(file) 来生成一个 RDD
  val fileRDDs = files.map { file =>
    val rdd = serializableConfOpt.map(_.value) match {
      case Some(config) => context.sparkContext.newAPIHadoopFile(
        file,
        fm.runtimeClass.asInstanceOf[Class[F]],
        km.runtimeClass.asInstanceOf[Class[K]],
        vm.runtimeClass.asInstanceOf[Class[V]],
        config)
      case None => context.sparkContext.newAPIHadoopFile[K, V, F](file)
    }
    if (rdd.partitions.size == 0) {
      logError("File " + file + " has no data in it. Spark Streaming can only ingest " +
        "files that have been \"moved\" to the directory assigned to the file stream. " +
        "Refer to the streaming programming guide for more details.")
    }
    rdd
  }
  // 将每个 file 对应的 RDD 进行 union,返回一个 union 后的 UnionRDD
  new UnionRDD(context.sparkContext, fileRDDs)
}

所以,结合以上 compute(validTime: Time) 和 filesToRDD(files: Seq[String]) 方法,我们得出 FileInputDStream 为每个 batch 生成 RDD 的实例过程如下:

  • (1) 先通过一个 findNewFiles() 方法,找到 validTime 以后产生的多个新 file
  • (2) 对每个新 file,都将其作为参数调用 sc.newAPIHadoopFile(file),生成一个 RDD 实例
  • (3) 将 (2) 中的多个新 file 对应的多个 RDD 实例进行 union,返回一个 union 后的 UnionRDD

其它 InputDStream 的为每个 batch 生成 RDD 实例的过程也比较类似了。

(b) 一般 DStream 的 compute(time) 实现

前一小节的 InputDStream 没有上游依赖的 DStream,可以直接为每个 batch 产生 RDD 实例。一般 DStream都是由transofrmation 生成的,都有上游依赖的 DStream,所以为了为 batch 产生 RDD 实例,就需要在 compute(time) 方法里先获取上游依赖的 DStream 产生的 RDD 实例。

具体的,我们看两个具体 DStream —— MappedDStream, FilteredDStream —— 的实现:

MappedDStream 的 compute(time) 实现

MappedDStream 很简单,全类实现如下:

package org.apache.spark.streaming.dstream

import org.apache.spark.streaming.{Duration, Time}
import org.apache.spark.rdd.RDD
import scala.reflect.ClassTag

private[streaming]
class MappedDStream[T: ClassTag, U: ClassTag] (
    parent: DStream[T],
    mapFunc: T => U
  ) extends DStream[U](parent.ssc) {

  override def dependencies: List[DStream[_]] = List(parent)

  override def slideDuration: Duration = parent.slideDuration

  override def compute(validTime: Time): Option[RDD[U]] = {
    parent.getOrCompute(validTime).map(_.map[U](mapFunc))
  }
}

可以看到,首先在构造函数里传入了两个重要内容:

  • parent,是本 MappedDStream 上游依赖的 DStream
  • mapFunc,是本次 map() 转换的具体函数
    • 在前文 DStream, DStreamGraph 详解 中的 quick example 里的 val pairs = words.map(word => (word, 1)) 的mapFunc 就是 word => (word, 1)

所以在 compute(time) 的具体实现里,就很简单了:

  • (1) 获取 parent DStream 在本 batch 里对应的 RDD 实例
  • (2) 在这个 parent RDD 实例上,以 mapFunc 为参数调用 .map(mapFunc) 方法,将得到的新 RDD 实例返回
    • 完全相当于用 RDD API 写了这样的代码:return parentRDD.map(mapFunc)

FilteredDStream 的 compute(time) 实现

再看看 FilteredDStream 的全部实现:

package org.apache.spark.streaming.dstream

import org.apache.spark.streaming.{Duration, Time}
import org.apache.spark.rdd.RDD
import scala.reflect.ClassTag

private[streaming]
class FilteredDStream[T: ClassTag](
    parent: DStream[T],
    filterFunc: T => Boolean
  ) extends DStream[T](parent.ssc) {

  override def dependencies: List[DStream[_]] = List(parent)

  override def slideDuration: Duration = parent.slideDuration

  override def compute(validTime: Time): Option[RDD[T]] = {
    parent.getOrCompute(validTime).map(_.filter(filterFunc))
  }
}

同 MappedDStream 一样,FilteredDStream 也在构造函数里传入了两个重要内容:

  • parent,是本 FilteredDStream 上游依赖的 DStream
  • filterFunc,是本次 filter() 转换的具体函数

所以在 compute(time) 的具体实现里,就很简单了:

  • (1) 获取 parent DStream 在本 batch 里对应的 RDD 实例
  • (2) 在这个 parent RDD 实例上,以 filterFunc 为参数调用 .filter(filterFunc) 方法,将得到的新 RDD 实例返回
    • 完全相当于用 RDD API 写了这样的代码:return parentRDD.filter(filterFunc)

总结一般 DStream 的 compute(time) 实现

总结上面 MappedDStream 和 FilteredDStream 的实现,可以看到:

  • DStream 的 .map() 操作生成了 MappedDStream,而 MappedDStream 在每个 batch 里生成 RDD 实例时,将对 parentRDD调用 RDD 的 .map() 操作 —— DStream.map() 操作完美复制为每个 batch 的 RDD.map()操作
  • DStream 的 .filter() 操作生成了 FilteredDStream,而 FilteredDStream 在每个 batch 里生成 RDD实例时,将对parentRDD 调用 RDD 的 .filter() 操作 —— DStream.filter() 操作完美复制为每个 batch 的 RDD.filter() 操作

在最开始, DStream 的 transformation 的 API 设计与 RDD 的 transformation 设计保持了一致,就使得,每一个dStreamA.transformation() 得到的新 dStreamB 能将 dStreamA.transformation() 操作完美复制为每个 batch 的rddA.transformation() 操作。

这也就是 DStream 能够作为 RDD 模板,在每个 batch 里实例化 RDD 的根本原因。

(c) ForEachDStream 的 compute(time) 实现

上面分析了 DStream 的 transformation 如何在 compute(time) 里复制为 RDD 的 transformation,下面我们分析 DStream 的output 如何在 compute(time) 里复制为 RDD 的 action。

我们前面讲过,对一个 DStream 进行 output 操作,将生成一个新的 ForEachDStream,这个 ForEachDStream用一个foreachFunc 成员来记录 output 的具体内容。

ForEachDStream 全部实现如下:

package org.apache.spark.streaming.dstream

import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.{Duration, Time}
import org.apache.spark.streaming.scheduler.Job
import scala.reflect.ClassTag

private[streaming]
class ForEachDStream[T: ClassTag] (
    parent: DStream[T],
    foreachFunc: (RDD[T], Time) => Unit
  ) extends DStream[Unit](parent.ssc) {

  override def dependencies: List[DStream[_]] = List(parent)

  override def slideDuration: Duration = parent.slideDuration

  override def compute(validTime: Time): Option[RDD[Unit]] = None

  override def generateJob(time: Time): Option[Job] = {
    parent.getOrCompute(time) match {
      case Some(rdd) =>
        val jobFunc = () => createRDDWithLocalProperties(time) {
          ssc.sparkContext.setCallSite(creationSite)
          foreachFunc(rdd, time)
        }
        Some(new Job(time, jobFunc))
      case None => None
    }
  }
}

同前面一样,ForEachDStream 也在构造函数里传入了两个重要内容:

  • parent,是本 ForEachDStream 上游依赖的 DStream
  • foreachFunc,是本次 output 的具体函数

所以在 compute(time) 的具体实现里,就很简单了:

  • (1) 获取 parent DStream 在本 batch 里对应的 RDD 实例
  • (2) 以这个 parent RDD 和本次 batch 的 time 为参数,调用 foreachFunc(parentRDD, time) 方法

例如,我们看看 DStream.print() 里 foreachFunc(rdd, time) 的具体实现:

def foreachFunc: (RDD[T], Time) => Unit = {
  val firstNum = rdd.take(num + 1)
  println("-------------------------------------------")
  println("Time: " + time)
  println("-------------------------------------------")
  firstNum.take(num).foreach(println)
  if (firstNum.length > num) println("...")
  println()
}

就可以知道,如果对着 rdd 调用上面这个 foreachFunc 的话,就会在每个 batch 里,都会在 rdd 上执行 .take() 获取一些元素到 driver 端,然后再 .foreach(println);也就形成了在 driver 端打印这个 DStream 的一些内容的效果了!

DStreamGraph 生成 RDD DAG 实例

在前文 Spark Streaming 实现思路与模块概述 中,我们曾经讲过,在每个 batch 时,都由 JobGenerator 来要求 RDD DAG “模板” 来创建 RDD DAG 实例,即下图中的第 (2) 步。

image

具体的,是 JobGenerator 来调用 DStreamGraph 的 generateJobs(time) 方法。

那么翻出来 generateJobs() 的实现:

// 来自 DStreamGraph
def generateJobs(time: Time): Seq[Job] = {
  logDebug("Generating jobs for time " + time)
  val jobs = this.synchronized {
    outputStreams.flatMap(outputStream => outputStream.generateJob(time))
  }
  logDebug("Generated " + jobs.length + " jobs for time " + time)
  jobs
}

也就是说,是 DStreamGraph 继续调用了每个 outputStream 的 generateJob(time) 方法 —— 而我们知道,只有 ForEachDStream 是 outputStream,所以将调用 ForEachDStream 的 generateJob(time) 方法。

image

举个例子,如上图,由于我们在代码里的两次 print() 操作产生了两个 ForEachDStream 节点 x 和 y,那么DStreamGraph.generateJobs(time) 就将先后调用 x.generateJob(time) 和 y.generateJob(time) 方法,并将各获得一个 Job。

但是…… x.generateJob(time) 和 y.generateJob(time) 的返回值 Job 到底是啥?那我们先插播一下 Job。

Spark Streaming 的 Job

Spark Streaming 里重新定义了一个 Job 类,功能与 Java 的 Runnable 差不多:一个 Job 能够自定义一个 func() 函数,而 Job 的 .run() 方法实现就是执行这个 func()。

// 节选自 org.apache.spark.streaming.scheduler.Job
private[streaming]
class Job(val time: Time, func: () => _) {
  ...

  def run() {
    _result = Try(func())
  }

  ...
}

所以其实 Job 的本质是将实际的 func() 定义和 func() 被调用分离了 —— 就像 Runnable 是将 run() 的具体定义和run() 的被调用分离了一样。

下面我们继续来看 x.generateJob(time) 和 y.generateJob(time) 实现。

x.generateJob(time) 过程

x 是一个 ForEachDStream,其 generateJob(time) 的实现如下:

// 来自 ForEachDStream
override def generateJob(time: Time): Option[Job] = {
  // 【首先调用 parentDStream 的 getOrCompute() 来获取 parentRDD】
  parent.getOrCompute(time) match {
    case Some(rdd) =>
      // 【然后定义 jobFunc 为在 parentRDD 上执行 foreachFun() 】
      val jobFunc = () => createRDDWithLocalProperties(time) {
        ssc.sparkContext.setCallSite(creationSite)
        foreachFunc(rdd, time)
      }
      // 【最后将 jobFunc 包装为 Job 返回】
      Some(new Job(time, jobFunc))
    case None => None
  }
}

就是这里牵扯到了 x 的 parentDStream.getOrCompute(time),即 d.getOrCompute(time);而 d.getOrCompute(time) 会牵扯c.getOrCompute(time),乃至 a.getOrCompute(time), b.getOrCompute(time)

用一个时序图来表达这里的调用关系会清晰很多:

image

所以最后的时候,由于对 x.generateJob(time) 形成的递归调用, 将形成一个 Job,其内容 func 如下图:

image

y.generateJob(time) 过程

同样的,y 节点生成 Job 的过程,与 x 节点的过程非常类似,只是在 b.getOrCompute(time) 时,会命中 get(time) 而不需要触发 compute(time) 了,这是因为该 RDD 实例已经在 x 节点的生成过程中被实例化过一次,所以在这里只需要取出来用就可以了。

同样,最后的时候,由于对 y.generateJob(time) 形成的递归调用, 将形成一个 Job,其内容 func 如下图:

image

返回 Seq[Job]

所以当 DStreamGraph.generateJobs(time) 结束时,会返回多个 Job,是因为作为 output stream 的每个 ForEachDStream 都通过 generateJob(time) 方法贡献了一个 Job。

image

比如在上图里,DStreamGraph.generateJobs(time) 会返回一个 Job 的序列,其大小为 2,其内容分别为:

image

至此,在给定的 batch 里,DStreamGraph.generateJobs(time) 的工作已经全部完成,Seq[Job] 作为结果返回给 JobGenerator后,JobGenerator 也会尽快提交到 JobSheduler 那里尽快调用 Job.run() 使得这 2 个 RDD DAG 尽快运行起来。

而且,每个新 batch 生成时,都会调用 DStreamGraph.generateJobs(time),也进而出发我们之前讨论这个 Job 生成过程,周而复始。

到此,整个 DStream 作为 RDD 的 “模板” 为每个 batch 实例化 RDD,DStreamGraph 作为 RDD DAG 的 “模板” 为每个 batch 实例化 RDD DAG,就分析完成了。

转自:GitHub

https://github.com/proflin/CoolplaySpark/blob/master/Spark%20Streaming%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%E7%B3%BB%E5%88%97/1.2%20DStream%20%E7%94%9F%E6%88%90%20RDD%20%E5%AE%9E%E4%BE%8B%E8%AF%A6%E8%A7%A3.md

转载请注明:人人都是数据咖 » DStream 生成 RDD 实例详解

移动端安全实战:如何用Unidbg动态分析小红书so加密协议(附CRC32校验破解) 本文深入解析小红书移动端so加密协议,通过Unidbg框架实现动态分析,重点破解CRC32校验与白盒AES算法。文章提供从环境搭建到协议逆向的全流程实战指南,涵盖SO文件反混淆、动态Hook技术及加密算法破解,为移动安全工程师提供高效分析方案。 阅读详情

相关推荐

攻防世界 Crypto 新手练习区 1-12 全详解

本篇是攻防世界 Crypto 新手练习区的全解

闵行小鱼塘 3733

1.2 DStream 生成 RDD 实例详解

1.2 DStream 生成 RDD 实例详解

wisgood的专栏 6132

GMSL2摄像头接入避坑指南:从FMC子卡配置到V4L2调用的完整流程(附Ubuntu20.04实测)

本文详细解析了GMSL2摄像头接入的全流程,从FMC子卡配置到V4L2调用的完整指南。基于XC7Z100平台实测经验,提供了硬件选型、带宽优化、Linux驱动配置及高分辨率采集的实战技巧,帮助开发者规避常见问题,提升系统稳定性与性能。

weixin_33737774的博客 418

DStream到RDD过程解析

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34166472的博客 1338

山东大学软件学院计算机组成原理课程设计实验二

文章目录一、实验时间二、实验内容1.设计异步模16加1计数器2.设计4位移位器3.超前进位16位ALU的设计 一、实验时间 2021年4月1日星期四,第五周 二、实验内容 1.设计异步模16加1计数器 基本功能:使用D触发器(dff元件)和异或门构建从0开始计数的模16加1计数器 对应的电路图(这里已经实现了预置初值的功能) 拓展功能: (1)实现模256加1计数器 (2)实现计数器预置初值的功能 这里复用了上面的模16加1计数器 这里异步触发器预置初值的功能是这样实现的: (1)首先将CLR端调为0,

叶卡捷琳堡的博客 5252

向量数据库安全实战:从Embedding反推到检索越权的全链路防护

随着RAG应用在企业中的普及,向量数据库已成为知识库系统的核心组件。但许多团队对向量数据的安全认知仍停留在传统数据库的账号密码、网络隔离和磁盘加密上。事实上,向量化并非加密,而是一种有损压缩的语义映射,向量本身可以被反推模型还原出原文关键信息,形成高保真的语义泄露通道。同时,相似度检索的模糊匹配特性打破了传统行列权限模型,使得越权检索和成员推断攻击成为新的安全威胁。理解这些原理,有助于企业在数据采集、向量化、索引构建、检索查询等环节构建分层防护体系,包括脱敏、扰动、过滤下推、网关控制等手段。本文从基础概念出

weixin_29323551的博客 259

1459. Rectangles Area----同列数据相减

Table:Points +---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | x_value | int | | y_value | int | +---------------+---------+ id is the primary key for this table. Each p.

betty1121的博客 400

详解各类以太网标准10BASE-T/100BASE-T4/100BASE-FX/1000BASE-X等

以太网是现实世界中最普遍的一种计算机网络。以太网有两类:第一类是经典以太网,第二类是交换式以太网,使用了一种称为交换机的设备连接不同的计算机。经典以太网是以太网的原始形式,运行速度从3-10 Mbps不等;而交换式以太网正是广泛应用的以太网,可运行在100Mbps、1000Mbps和10000Mbps高速率,分别以快速以太网、千兆以太网和万兆以太网的形式呈现

不积跬步,无以至千里! 5万+

1. 理解 RDD、DataFrame、DataSet、DStream

理解 RDD、DataFrame、DataSet、DStream

doing a 责任心 dataer 854

【机器人】线性方程最小二乘解法对机械臂DH参数进行标定

1.前言 看了一篇文章,觉得里面的DH参数标定法讲的很清晰,便使用Matlab复现了一下,效果还可以,特写此文记录。 2.原理 2.1.误差最佳值的最小二乘计算 有研究结果表明:几乎95%的机器人位置误差都是由机器人内部运动学的不准确描述引起的,所以对DH模型参数进行标定是很有必要的。 DH参数物理含义:选自《机器人学、机器视觉与控制-Matlab基础》 当DH参数确定后,我们...

要恰饭得嘛 1万+

手把手教你学Simulink--基于电能质量与无功补偿的场景实例:统一电能质量调节器(UPQC)的联合控制仿真

在现代电力系统中,电能质量问题有源电力滤波器(APF)→ 治理谐波与无功动态电压恢复器(DVR)→ 补偿电压暂降/暂升静止无功发生器(SVG)→ 无功补偿与电压支撑而统一电能质量调节器(Unified Power Quality Conditioner, UPQC)是一种集串联补偿与并联补偿于一体的全能型电能质量治理装置✅ 电压类问题:暂降、暂升、不平衡、闪变✅ 电流类问题:谐波、无功、三相不平衡✅ 实现双向有功交换(储能型)串联单元(DVR功能):串联于线路,控制电源侧电压质量并联单元。

MHD0815的博客 238

Dstream生成RDD实例详解

DStream 生成 RDD 实例详解 [酷玩 Spark] Spark Streaming 源码解析系列 ,返回目录请 猛戳这里 「腾讯·广点通」技术团队荣誉出品 本系列内容适用范围: * 2016.12.28 update, Spark 2.1 全系列 √ (2.1.0) * 2016.11.14 update, Spark 2.0 全系列 √ (2.0.0, 2.0.1, 2

5309

南方电网专业面试题(电气类-继电保护)(目录)

南方电网专业面试题(电气类-继电保护)(目录) 这些面试题围绕继电保护的基本概念、工作原理、分类、性能要求,以及变压器、断路器、母线保护、自动重合闸等电力系统关键设备的保护机制和操作原则展开,旨在评估应聘者对电力系统保护和控制策略的深入理解和实际应用能力。

weixin_44808274的博客 2159

######好好好#######DStream 生成 RDD 实例详解

DStream 生成 RDD 实例详解 [酷玩 Spark] Spark Streaming 源码解析系列 ,返回目录请 猛戳这里 「腾讯·广点通」技术团队荣誉出品 本系列内容适用范围: * 2016.12.28 update, Spark 2.1 全系列 √ (2.1.0) * 2016.11.14 update, Spark 2.0 全系列 √ (2.0.0, 2.0.1, 2

木东的博客 382

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Spark Streaming生成RDD并执行Spark Job源码内幕解密

本博文主要包含以下内容: DStream产生RDD的案例实战演示 DStream作为RDD模板的原理机制 常见DStream生产RDD源码解密 这种常见的DStream包含三种类型,一种是输入的级别的InputDStream,第二种transformationDStream,第三种输出级别的ForeachDStream。博文主要代码如下:object NetworkWordCount { def

吾心光明 1550

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

第8课:Spark Streaming源码解读之RDD生成全生命周期彻底研究和思考

本篇博客将详细探讨DStream模板下的RDD是如何被创建,然后被执行的。在开始叙述之前,先来思考几个问题,本篇文章也就是基于此问题构建的。1. RDD是谁产生的?2. 如何产生RDD?带着这两个问题开启我们的探索之旅。一:实战WordCount源码如下:objectWordCount{defmain(args:Array[String]):Unit={...

weixin_33961829的博客 121

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Spark源码解析:DStream

0x00 前言 本篇是Spark源码解析的第二篇,主要通过源码分析Spark Streaming设计中最重要的一个概念——DStream。 本篇主要来分析Spark Streaming中的Dstream,重要性不必多讲,明白了Spark这个几个数据结构,容易对Spark有一个整体的把握。和RDD那篇文章类似,虽说是分析Dstream,但是整篇文章会围绕着一个具体的例子来展开。算是对Spark S

木东居士 8940

8 DStream与RDD

DStream与RDD关系彻底研究 Streaming中RDD的生成彻底研究

Hipparchus的博客 4545

解读Spark Streaming RDD的全生命周期

本节主要内容: 一、DStream与RDD关系的彻底的研究 二、StreamingRDD的生成彻底研究 Spark Streaming RDD思考三个关键的问题: RDD本身是基本对象,根据一定时间定时产生RDD的对象,随着时间的积累,不对其管理的话会导致内存会溢出,所以在BatchDuration时间内执行完RDD操作后,需对RDD进行管理。 1、DStream生成RDD的过程,DSt...

weixin_30509393的博客 156

Spark Streaming源码解读之生成全生命周期彻底研究与思考

本期内容 : DStream与RDD关系彻底研究 Streaming中RDD的生成彻底研究      问题的提出:   1、 RDD是怎么生成的,依靠什么生成   2、执行时是否与Spark Core上的RDD执行有什么不同的   3、 运行之后我们要怎么处理     为什么有第三点 : 是因为Spark Streaming 中会随着相关触发条件,窗口Wind...

weixin_30469895的博客 96

Spark Streaming源码解读之RDD生成全生命周期彻底研究和思考

本博文内容主要是 : DStream与RDD关系彻底研究 Streaming中RDD的生成彻底研究 问题的提出 :   1、RDD是依靠谁产生的? 如何产生RDD?  2、执行时是否与Spark Core上的RDD执行有什么不同的  3、 运行之后对RDD要怎么处理    为什么有第三点 : 是因为Spark Streaming 中会随着相关触发条件,窗口Window滑动的时候都会不断的产生RDD

吾心光明 2014

Spark学习笔记(8)源码解读之RDD生成全生命周期

本段内容: 1 DStream与RDD关系的彻底的研究 2 StreamingRDD的生成彻底研究   我们有必要来思考三个重要有价值的问题:   1 DStream生成RDD的过程,DStream到底是怎么生成RDD的?   2 DStream和RDD到底什么关系?   3 RDD生成后是怎么管理的?   有些Spark Streaming应用程序中的最后部分,会有print输

Jason的专栏 527

Spark 定制版:008~Spark Streaming源码解读之RDD生成全生命周期彻底研究和思考

本讲内容:a. DStream与RDD关系的彻底的研究 b. Streaming中RDD的生成彻底研究注:本讲内容基于Spark 1.6.1版本(在2016年5月来说是Spark最新版本)讲解。上节回顾上节课,我们重点给大家揭秘了JobScheduler内幕;可以说JobScheduler是整个Spark Streming的调度的核心,其地位相当于Spark Core中的DAGScheduler

zisheng_wang_DATA的博客 1万+
上一篇: 深入分析Parquet列式存储格式
下一篇: Spark Streaming 实现思路与模块概述
Next__One
博客等级 码龄9年 14粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值