Spark Streaming超神学习05

1.流批对比

在这里插入图片描述

Spark Streaming类似于Apache Storm,用于流式数据的处理。根据其官方文档介绍,Spark Streaming有高吞吐量和容错能力强等特点.

2.输入位置和输出位置

在这里插入图片描述

和Spark基于RDD的概念很相似,Spark Streaming使用离散化流(discretized stream)作为抽象表示,叫作DStream。DStream 是随时间推移而收到的数据的序列。在内部,每个时间区间收到的数据都作为 RDD 存在,而 DStream 是由这些 RDD 所组成的序列(因此 得名“离散化”)。

在这里插入图片描述
Spark Streaming的编程抽象是离散化流,也就是DStream。它是一个 RDD 序列,每个RDD代表数据流中一个时间片内的数据。

在这里插入图片描述

3.基于receiver的streaming作业执行流程

在这里插入图片描述

4.什么是DStreams

Discretized Stream是Spark Streaming的基础抽象,代表持续性的数据流和经过各种Spark原语操作后的结果数据流。在内部实现上,DStream是一系列连续的RDD来表示。每个RDD含有一段时间间隔内的数据,
Spark Streaming把一系列连续的批次称为Dstream。

5.Dstream的特点:

就是将流式计算分解成为一系列确定并且较小的批处理作业
可以将失败或者执行较慢的任务在其他节点上并行执行
有较强的的容错能力,基于lineage
Dstream内含high-level operations进行处理
Dstream内部实现为一个RDD序列
在这里插入图片描述
在这里插入图片描述

6.DStreams输入

Spark Streaming原生支持一些不同的数据源。一些“核心”数据源已经被打包到Spark Streaming 的 Maven 工件中,而其他的一些则可以通过 spark-streaming-kafka 等附加工件获取。

Steaming的数据源和接收器

数据源:基本数据源/高级数据源
基本数据源:socket、file,akka actoer。Steaming中自带了该数据源的读取API
高级数据源:kafka,flume,kinesis,Twitter等其他的数据。必须单独导入集成的JAR包spark-streaming-[projectname]_2.10

接收器:

Socket数据源,有一个接收器,用户接受Socket的数据。每一个接收器必须占用一个cores来接收数据。如果资源不足,那么任务就会处于等待状态。

CPU 核心:

每个接收器都以 Spark 执行器程序中一个长期运行的任务的形式运行,因此会占据分配给应用的 CPU 核心。此外,我们还需要有可用的 CPU 核心来处理数据。这意味着如果要运行多个接收器,就必须至少有和接收器数目相同的核心数,还要加上用来完成计算所需要的核心数。例如,如果我们想要在流计算应用中运行 10 个接收器,那么至少需要为应用分配 11 个 CPU 核心。所以如果在本地模式运行,不要使用local或者local[1]。

7.Receiver读取kafka数据特点

在spark的executor中,启动一个接收器,专门用于读取kafka的数据,然后存入到内存中,供sparkStreaming消费
1、为了保证数据0丢失,WAL,数据会保存2份,有冗余
2、Receiver是单点读数据,如果挂掉,程序不能运行
3、数据读到executor内存中,增大了内存使用的压力,如果消费不及时,会造成数据积压
如下图:
在这里插入图片描述

还有几个需要注意的点:

1、Kafka中topic的partition与Spark Streaming中生成的RDD的partition无关,因此,在KafkaUtils.createStream()中,增加某个topic的partition的数量,只会增加单个Receiver消费topic的线程数,也就是读取Kafka中topic partition的线程数量,它不会增加Spark在处理数据时的并行性。
2、可以使用不同的consumer group和topic创建多个Kafka输入DStream,以使用多个receiver并行接收数据。
3、如果已使用HDFS等复制文件系统启用了“预读日志”,则接收的数据已在日志中复制。因此,输入流的存储级别的存储级别StorageLevel.MEMORY_AND_DISK_SER(即,使用KafkaUtils.createStream(…, StorageLevel.MEMORY_AND_DISK_SER))。

8.Direct方式

Direct:直连模式,在spark1.3之后,引入了Direct方式。不同于Receiver的方式,Direct方式没有receiver这一层,其会周期性的获取Kafka中每个topic的每个partition中的最新offsets,并且相应的定义要在每个batch中处理偏移范围,当启动处理数据的作业时,kafka的简单的消费者api用于从kafka读取定义的偏移范围 。其形式如下图:

在这里插入图片描述
这种方法相较于Receiver方式的优势在于:

1、简化的并行:在Receiver的方式中我们提到创建多个Receiver之后利用union来合并成一个Dstream的方式提高数据传输并行度。而在Direct方式中,Kafka中的partition与RDD中的partition是一一对应的并行读取Kafka数据,这种映射关系也更利于理解和优化。
2、高效:在Receiver的方式中,为了达到0数据丢失需要将数据存入Write Ahead Log中,这样在Kafka和日志中就保存了两份数据,浪费!而第二种方式不存在这个问题,只要我们Kafka的数据保留时间足够长,我们都能够从Kafka进行数据恢复。
3、精确一次:在Receiver的方式中,使用的是Kafka的高阶API接口从Zookeeper中获取offset值,这也是传统的从Kafka中读取数据的方式,但由于Spark Streaming消费的数据和Zookeeper中记录的offset不同步,这种方式偶尔会造成数据重复消费。而第二种方式,直接使用了简单的低阶Kafka API,Offsets则利用Spark Streaming的checkpoints进行记录,消除了这种不一致性。
请注意,此方法的一个缺点是它不会更新Zookeeper中的偏移量,因此基于Zookeeper的Kafka监视工具将不会显示进度。但是,您可以在每个批处理中访问此方法处理的偏移量,并自行更新Zookeeper。

直连模式特点:tatch time 每隔一段时间,去kafka读取一批数据,然后消费
简化并行度,rdd的分区数量=topic的分区数量
数据存储于kafka中,没有数据冗余
不存在单点问题
效率高
可以实现仅消费一次的语义 exactly-once语义

代码入门

socket模拟实时不间断接收数据

/**
 * SparkStreaming的入门案例
 *      通过网络socket来模拟实时不断产生数据并处理
 *  linux的安装:
 *      yum -y installl nc
 *      nc -lk 9999启动端口发送数据
 *  StreamingContext剖析:
 *      local       :是当前程序分配一个工作线程
 *      local[*]    :给当前程序分配可以用工作线程(通常会>=2)
 *   这个改动造成程序只接收数据,而不进行处理,那么也就意味着,streaming需要使用线程资源既要接收数据,还有消费数据,而且优先接收数据,接收数据要独占一个线程字段。
 *
 *   在本地模式下面,去处理receiver到的数据的时候,线程资源最好设置大于1。
 *
 */
object Demo1 {
   
  def main(args: Array[String]): Unit = {
   
    val conf = new SparkConf().setAppName("Demo1").setMaster("local[*]")
    val batchDuration = Seconds(2)//每2s提交一次sparkstreaming的作业
    val sc = new StreamingContext(conf,batchDuration)
    //加载外部数据
    val value:ReceiverInputDStream[String] = sc.socketTextStream("hadoop003", 9999, storageLevel = StorageLevel.MEMORY_AND_DISK_SER_2)
    val ds:DStream[String] = value.flatMap(line => line.split("\\s+"))
    val ds1:DStream[(String,Int)] = ds.map(word => (word, 1))
    val ds2:DStream[(String,Int)] = ds1.reduceByKey(_ + _)
    ds2.print()
    /*
            start操作,是用来启动streaming程序的计算,如果不执行start操作,程序压根儿不会执行
         */
    sc.start()
    /*
     Adding new inputs, transformations, and output operations after starting a context is not supported
     在程序启动之后,也就是start之后,不可以再添加任何的业务逻辑
  */
    //        ret.print()
    /*
           如果没有awaitTermination方法,程序不会持续不断的运行,说白就是把driver设置成为一个后台的守护线程
        */
    sc.awaitTermination(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值