SparkStreaming学习笔记

一、什么是SparkStreaming

Spark Streaming 是 Spark 核心 API 的一个扩展,可以实现高吞吐量的、具备容错机制的实时流数据的处理。为了实现流式处理数据。

二、创建SparkStreaming环境对象

首先引入maven对象

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-streaming_2.12</artifactId>
    <version>3.1.1</version>
</dependency>
val conf = new SparkConf().setMaster("local[*]").setAppName("streaming")

// 创建环境对象,需要传递两个参数  第一个是环境配置 第二个是采集的周期
val streamContext = new StreamingContext(conf, Seconds(3))

... // 业务代码

streamContext.start()   // 开始采集数据

...  // 这里可以放一些自定义的DStream值

streamContext.awaitTermination()  // 等待采集器结束
streamContext.stop()

三、SparkStreaming读入数据

1. 通过socket方式读入数据

def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[*]").setAppName("streaming")
    val streamContext = new StreamingContext(conf, Seconds(3))

    // 通过socket获取数据
    val lines = streamContext.socketTextStream("localhost", 9999)
    lines .print()

    streamContext.start()
    streamContext.awaitTermination()
}

2. 自定义DS数据

def main(args: Array[String]): Unit = {
  val conf = new SparkConf().setMaster("local[*]").setAppName("streaming")
  val streamContext = new StreamingContext(conf, Seconds(3))

  // 创建一个dstream  类似创建一个rdd
  val intQueue = new mutable.Queue[RDD[Int]]()
  // oneAtATime 是否在每个间隔中只应从队列中使用一个RDD
  val Dstream = streamContext.queueStream(intQueue, oneAtATime = false)
    
  // 开始采集数据,数据开始采集之后放值不是一开始就是赋值好
  streamContext.start()
  // 将数据入队
  intQueue.enqueue(streamContext.sparkContext.makeRDD(seq = 1 to 30, numSlices = 8))
  streamContext.awaitTermination()
}

四、自定义数据采集器

object Dstream {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[*]").setAppName("streaming")
    val streamContext = new StreamingContext(conf, Seconds(3))

    // 使用自定义采集数据
    val messageDs = streamContext.receiverStream(new MyReceiver())
    messageDs.print()

    streamContext.start()
    streamContext.awaitTermination()
  }

  // 自定义数据采集器,需要继承Receiver并传一个接收数据的泛型,参数传存储级别
  class MyReceiver extends Receiver[String](StorageLevel.MEMORY_ONLY){
    var tag = true;

    // 开始采集数据的时候需要开辟另外一个线程
    override def onStart(): Unit = {
      new Thread(() => {
        while (tag){
          val message = new Random().nextInt().toString

          // 自动将数据存储
          store(message)
          Thread.sleep(500)
        }
      }).start()
    }

    override def onStop(): Unit = {
      tag = false
    }
  }
}

五、从kafka读数据

从kafka读取数据需要引入maven

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-streaming-kafka-0-10_2.12</artifactId>
    <version>3.1.1</version>
</dependency>

读取数据

def main(args: Array[String]): Unit = {
  val conf = new SparkConf().setMaster("local[*]").setAppName("streaming")
  val streamContext = new StreamingContext(conf, Seconds(3))

  val kafkaPara: Map[String, Object] = Map[String, Object](
    // 这里是kafka的访问地址或者是集群地址
    ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG -> "",
    // 组名称
    ConsumerConfig.GROUP_ID_CONFIG -> "",
    "key.deserializer" -> "org.apache.kafka.common.serialization.StringDeserializer",
    "value.deserializer" -> "org.apache.kafka.common.serialization.StringDeserializer"
  )

  // kafka util 创建连接, 需要一个泛型用于代表接受参数的类型
  val kafkaStream: InputDStream[ConsumerRecord[String, String]] = KafkaUtils.createDirectStream[String, String](streamContext,
    LocationStrategies.PreferConsistent, // 类似sparkCore的首选位置
    // 消费者策略,需要topic的名称和kafka的参数
    ConsumerStrategies.Subscribe[String, String](List("asd"), kafkaPara)
  )

  // _.value()就会获得kafka传过来的值
  kafkaStream.map(_.value())
}

六、数据的状态

有状态和无状态的区别:

无状态操作只会对当前周期内的数据进行处理。

有状态就是数据有状态,可以对所有数据做汇总,并不是对一批数据进行汇总。

def main(args: Array[String]): Unit = {
  val conf = new SparkConf().setMaster("local[*]").setAppName("streaming")
  val streamContext = new StreamingContext(conf, Seconds(3))

  // 使用有状态的数据,需要设置检查点路径
  streamContext.checkpoint("cp")

  val lines = streamContext.socketTextStream("localhost", 9999)
  val words = lines.flatMap(_.split(" "))
  val wordToOne: DStream[(String, Int)] = words.map((_, 1))

  // 根据key更新数据状态,需要传两个参数,第一个参数 相同key的value数据  第二个参数 缓冲区相同key的value数据
  wordToOne.updateStateByKey((seq: Seq[Int], opt: Option[Int]) => {
    // 由于这里拿到的都是二元组的第二个数据,直接sum进行求和
    val value = opt.getOrElse(0) + seq.sum
    Option(value)  // 返回需要是缓冲区类型
  }).print()

  streamContext.start()
  streamContext.awaitTermination()
}

七、转换操作

val lines = streamContext.socketTextStream("localhost", 9999)

// 用于周期性执行代码或者Dstream功能不完善 可以直接用底层rdd的方法
val rawRdd: DStream[String] = lines.transform(rdd => rdd)

transform和map的区别

val rawRdd: DStream[String] = lines.transform(
  rdd => {
    // 在这里的代码会周期性的执行在driver端
    rdd.map(a => {
      a  // 在executor执行
    })
  }
)
    
val rawMap: DStream[String] = lines.map(
  rdd => {
    rdd  // 在executor执行
  }
)

八、无状态的join操作

val line1 = streamContext.socketTextStream("localhost", 9999)
val line2 = streamContext.socketTextStream("localhost", 8888)

val stream1 = line1.map((_, 0))
val stream2 = line2.map((_, 1))

// 无状态的操作join, 相同的key把关联的v放在一起
val value: DStream[(String, (Int, Int))] = stream1.join(stream2)

九、窗口操作(有状态)

val lines = streamContext.socketTextStream("localhost", 9999)
val wordToOne: DStream[(String, Int)] = lines.map((_, 1))

// 窗口的周期最好是采集周期的整数倍, 默认情况一个采集周期一个滑动
// 第一个参数 窗口大小  第二个参数 步长(防止窗口出现重叠)
val Dstream = wordToOne.window(Seconds(6), slideDuration = Seconds(6))
val value = Dstream.reduceByKey(_ + _)

可以自定义对于新数据和移除数据的处理

val lines = streamContext.socketTextStream("localhost", 9999)
val wordToOne: DStream[(String, Int)] = lines.map((_, 1))

//  需要设置检查点  按照窗口进行叠加
val value = wordToOne.reduceByKeyAndWindow(
  (x, y) => {x + y},  // 当窗口滑动的时候新进来的数据怎么做(这里新增的数据做加法)
  (x, y) => {x - y},  // 当窗口滑动的时候新移除的数据怎么做(这里新增的数据做减 法)
  Seconds(9),          // 窗口大小
  Seconds(3)          // 窗口周期
)

十、优雅的关闭

val conf = new SparkConf().setMaster("local[*]").setAppName("streaming")
val streamContext = new StreamingContext(conf, Seconds(6))
val line1 = streamContext.socketTextStream("localhost", 9999)
val stream1 = line1.map((_, 0))
stream1.start()

// 需要开启另外一个线程进行关闭,一般去读取第三方数据的状态,例如mysql、redis等等
new Thread(() => {
  // 这里只是模拟
  while(true){
    if(streamContext.getState() == StreamingContextState.ACTIVE){
      // 优雅的关闭, 计算节点不再接收新的数据 等节点处理完内部数据以后在进行关闭
      streamContext.stop(true,true)
    }
  }
}).start()

streamContext.awaitTermination()

十一、数据的恢复

// 创建检查点 每次从检查点恢复数据,如果没有数据就去创建
val context = StreamingContext.getActiveOrCreate("cp", () => {
  val conf = new SparkConf().setMaster("local[*]").setAppName("streaming")
  val streamContext = new StreamingContext(conf, Seconds(6))
  val line1 = streamContext.socketTextStream("localhost", 9999)
  val stream1 = line1.map((_, 0))
  stream1.print()

  streamContext
})
context.checkpoint("cp")
context.start()
context.awaitTermination()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Kafka和Spark Streaming是大数据领域中非常重要的技术,它们可以协同工作,实现实时数据处理和分析。Kafka是一个分布式的消息队列系统,可以高效地处理海量数据流,而Spark Streaming则是一个基于Spark的流处理框架,可以实现实时数据处理和分析。在学习Kafka和Spark Streaming时,需要掌握它们的基本概念、原理和使用方法,以及如何将它们结合起来实现实时数据处理和分析。同时,还需要了解Kafka和Spark Streaming的优缺点,以及如何优化它们的性能和可靠性。 ### 回答2: Kafka是一个高性能,可扩展的分布式消息系统。它通过将消息划分成一个或多个主题,然后将这些主题划分成一个或多个分区来进行实现。Kafka是由LinkedIn开发的,由Apache基金会进行管理。它的主要设计目标是支持分布式处理,如流处理和批处理等。Kafka通过使用Zookeeper来进行节点管理和故障转移,能够快速处理海量的数据。Kafka采用发布/订阅模式,支持多个消费者订阅同一个主题,每个消费者可以读取主题的所有分区数据,也可以选择读取其中的某个分区。 Spark Streaming是一个流处理框架,它能够利用Spark的分布式处理能力来对实时数据进行处理。Spark Streaming采用微批处理的方式,将实时数据流切片成一段一段的,并通过并行处理的方式进行计算。Spark Streaming的数据源可以是Kafka、Flume或者TCP sockets等。与Kafka相比,Spark Streaming更适合于需要进行实时计算的场景,例如:实时日志分析、实时推荐、实时风控等。同时,Spark Streaming还能够与Spark的批处理进行无缝对接,实现流处理与批处理的统一计算引擎。Spark Streaming支持机器学习、图计算等高级计算库,能够为用户提供更强大的计算能力。 学习Kafka和Spark Streaming的过程中,需要掌握Java、Scala等编程语言基础知识,并具备分布式系统的相关知识。对于Kafka,需要了解其基本概念、架构、API等,理解消息系统、发布/订阅模式、分区等内容。对于Spark Streaming,需要掌握其基本概念、流式计算流程、数据源等,同时也要熟悉Spark的RDD、DataFrame等相关知识。在学习中,需要结合实际项目,进行代码实践和调试,同时不断学习、思考和总结,以加深对Kafka和Spark Streaming的理解和应用。 ### 回答3: Kafka是由Apache SoftWare Foundation开发的一种分布式发布/订阅消息系统。其主要目的是为数据传输提供一种高吞吐量、低延迟的解决方案。Kafka提供了一种可靠的、持久化的、实时的数据传输方式,适用于众多的场景,如:日志收集、数据传输、消息系统等。 Kafka的特点: 1、高吞吐量:Kafka可以支持非常高的数据传输吞吐量,同时保持低延迟和高稳定性。 2、可扩展性:Kafka可以轻松扩展以适应更大的数据需求,并可以在运行时添加新的主题分区。 3、持久化:Kafka保证数据能够可靠地在分布式集群中传输,同时保证数据不会丢失或者被意外删除。 4、多样化的客户端:Kafka提供了多种语言的客户端接口,以满足不同的开发需求。 SparkStreaming 是由Apache Spark社区发展的一个实时数据处理框架。它用于将实时数据流分成小批处理,可以跨越不同的时间窗口进行计算。Spark Streaming提供了与Spark非常相似的编程模型,同时支持不同的输入源,包括社交媒体、传感器、消息队列等。 SparkStreaming的特点: 1、处理速度快:它可以支持毫秒级别的处理速度,并且可以在分布式系统中实现高吞吐量。 2、支持多种数据源:Spark Streaming可以从多种类型的数据源中读取数据,如HDFS、Flume、Kafka等。 3、编程简单:Spark Streaming提供了与Spark相似的编程模式,使得开发人员可以将Spark StreamingSpark整合在一起进行处理。 4、高容错性:Spark Streaming在分布式环境中实现了高可靠性和容错性,使得它可以支持大规模的实时数据处理需求。 总之,Kafka和Spark Streaming这两个工具是在大数据处理领域中非常重要的工具。它们可以很好地相互结合,支持大规模的实时数据处理和分析,进而为企业提供更好更快的数据处理方案。如果你对这两个技术感兴趣,可以从官方文档和教程开始学习,逐步掌握它们的定义、特点、应用场景和基本使用方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值