SparkStreaming :流处理基础和DStream

本文探讨流处理的基础概念及应用场景,强调其在实时数据分析中的优势与挑战。深入解析Spark DStream API,演示其实现原理及wordcount示例,同时讨论微批量处理模式与连续处理模式的选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 什么是流处理

基础概念

流处理是连续处理新到来的数据以更新计算结果的行为,我们将流处理定义为在无边界数据集上的增量处理。 它是一系列到达流处理系统的事件(例如,信用卡交易,点击网站动作,或从物联网 IoT 传感器读取的数据),用户应用程序对此事件流可以执行各种查询操作。批处理是在固定大小输入数据集上进行计算的,也可以进行查询计算,但只计算一次结果。虽然流处理和批处理是不同的,但在实践中需要一起使用。(需要注意的是,应用程序中的任何业务逻辑都需要在流处理和批处理执行之间保持一致)

应用场景

  1. 通知和报警
  2. 实时报告
  3. 增量ETL
  4. 实时数据更新来通过实时服务
  5. 实时决策
  6. 在线机器学习

流处理的优点

  1. 降低延迟时间:当你的应用程序需要快速响应时间( 在分钟、秒或毫秒级别上),你需要一个可以将状态保存在内存中的流处理系统,以获得更好的性能
  2. 流处理系统可以记住以前计算的状态,只计算新数据(自动增量计算)。

流处理面临的挑战

  1. 基于应用程序时间戳(也称为事件时间) 处理无序数据
    如:接收某传感器数据,因延迟或者重新传输,输入记录无序地到达应用程序。会收到以下更新序列:
{value: 1, time: "2017-04-07T00: 00: 00"}
{value: 2, time: "2017-04-07T01: 00: 00"}
{value: 5, time: "2017-04-07T02: 00: 00"}
{value: 10, time: "2017-04-07T01: 30: 00"}
{value: 7, time: "2017-04-07T03: 00: 00"} 

在批处理中,我们可以简单地按time字段进行排序,让10在2和5之间到来。但在流处理系统中,是比较困难的,原因是流处理系统将单独接收每个事件,并且需要跟踪事件的某些状态以记住值为 2 和 5 的事件,并意识到值为 10 的事件是在它们之间, 这种在流中记住事件状态的需求带来了更多的挑战

  1. 维持大量的状态
    如:如果你有一个海量的数据集(例如,数以百万计的传感器流) 并且状态本身是巨大的,应该如何维持状态。如果系统中的机器出现故障了,丢失了一些状态怎么办。
  2. 支持高吞吐量
    批量处理数据使得数据处理的吞吐量大大高于许多流处理系统。
  3. 即使有机器故障也仅需对事件进行一次处理
  4. 处理负载不平衡和拖延者
  5. 快速响应时间
  6. 事务性地向输出系统写入数据和事务性地向输出系统写入数据
  7. 在运行时更新应用程序的业务逻辑

流处理设计要点

  1. 记录级别API与声明式API
    记录级别API:给用户提供一个获取每条流数据记录的接口,将每个事件传递给应用程序,并使用自定义代码进行响应。缺点:上述挑战中所遇到的大多数复杂因素都要完全由应用程序负责,所以像记录级别 API 这种低级API 需要深厚的专业知识才能开发和维护。
    声明式 API:应用程序为了响应每个新事件指定要计算的内容,而不是如何计算,也不需要考虑如何从失败中恢复。如Spark的DStreamAPI,DStream API 自动跟踪每个操作处理的数据量,可靠地保存相关状态,并在需要时从失败中恢复计算 。

  2. 基于事件时间与基于处理时间
    事件时间( event time)是根据数据源插入记录中的时间戳来处理数据的概念 ;
    处理时间(processing time)是流处理应用程序在接收记录时的时间 ;

当使用事件时间时,记录可能会出现无序状况(例如,如果记录从不同的网络路径返回),并且不同的数据源可能也无法同步(对于标记相同事件时间的记录, 某些记录可能比其他记录晚到达)。如果你的应用程序从可能产生延迟的远程数据源 (如移动电话或物联网设备) 收集数据,则基于事件时间的处理方式就非常必要。如果不基于事件时间,你可能在某些数据延迟到达时无法发现某些重要的模式

当使用事件时间时,需要注意几个问题:允许系统合并延迟事件的方式跟踪状态,以及确定何时在事件时间内输出给定时间窗口的结果是安全的

  1. 连续处理与微批量处理
    最后一个设计选择通常是确定连续处理( Continuous Processing)模式还是微批量处理( Microbatch Processing)模式。
    对于连续处理系统:系统中的每个节点都不断地侦听来自其他节点的消息并将新的更新输出到其子节点。 在输入数据速率较低时,连续处理提供尽可能低的处理延迟,这是连续处理的优势,因为每个节点都会立即响应新消息。但是,连续处理系统通常具有较低的最大吞吐量,因为它们处理每条记录的开销都很大 (例如,调用操作系统将数据包发送到下游节点)。此外,连续处理系统通常具有固定的计算拓扑如果不停止整个系统,在运行状态下是不能够改动的,这也可能会导致负载均衡的问题。
    在这里插入图片描述

对于微批次处理系统:微批量处理系统等待积累少量的输入数据( 比如 500 ms 的数据) ,然后使用分布式任务集合并行处理每个批次,类似于在 Spark 中执行批处理作业。微批量处理系统通常可以在每个节点上实现高吞吐量,因为它们利用与批处理系统相同的优化操作,并且不会引入频繁处理单个记录的额外开销 。
因此,微批量处理只需要较少的节点就可以应对相同生产速率的数据。微批量处理系统还可以使用动态负载平衡技术来应对不断变化的工作负载 ,缺点是由于等待累积一个微批量而导致更长的响应延迟。

在这里插入图片描述
在这两种执行模式之间进行选择时,最主要因素是你期望的延迟和总的操作成本 (TCO)。 在实际生产中,在处理大规模数据并需要分布式计算的流处理应用程序往往优先考虑吞吐量。微批量处理系统可能将延迟从 100 毫秒延长到秒。在这种机制下, 通常需要较少的节点就可以达到要求的吞吐量,因而降低了运营成本 。 若是为了获得更低的延迟,你应该考虑一个连续处理系统,或使用一个微批量处理系统与快速服务层( fast serving layer)结合以提供低延迟查询

2.DStream

DStream介绍

DStream是SparkStreaming的低级API,DStream API 纯粹是基于微批量处理模式的,它是声明式 (基于功能的) API,但不支持事件时间。在 Apache Spark 2.2 中,SparkStreaming完全支持结构化流处理 API( Structured Streaming API)。

DStream API 有几个限制:首先,它完全基于 Java/Python 对象和函数,而不是 DataFrame 和Dataset 中丰富的结构化表概念,这不利于执行引擎进行优化。其次, DStream API 纯粹基于处理时间(要处理事件时间操作,应用程序需要自己实现它们)。最后, DStream 只能以微批量方式运行,并在其 API 的某些部分暴露了微批量的持续时间,这使得其难以支持其他执行模式。

DStream应用

  1. DStream是SparkStreaming中最基本的抽象(代理),代表一系列连续的数据流,本质上是一系列连续的RDD,你对DStream进行操作,就是对RDD进行操作。DStream也可以理解成一个RDD的工厂,每隔一段时间就生成一个RDD,该DStream里面生产都是相同业务逻辑的RDD,只不过是RDD里面要读取数据的不相同。
  2. DSteam和DStream之间存在依赖关系,在一个固定的时间点,对个存在依赖关系的DSrteam对应的RDD也存在依赖关系,每个一个固定的时间,其实生产了一个小的DAG,周期性的将生成的小DAG提交到集群中运行。
    在这里插入图片描述
    在这里插入图片描述

DStream-wordcount

//离线任务是创建SparkContext,实时计算要StreamingContext
val conf = new SparkConf().setAppName("StreamingWordCount").setMaster("local[2]")
val context = new SparkContext(conf)
//StreamingContext是对SparkContext的包装
//第二个参数是小批次产生的时间间隔
val ssc = new StreamingContext(context,Milliseconds(5000))
//有了StreamingContext,就可以创建SparkStreaming的抽象了DSteam
//从一个socket端口中读取数据
//在Linux上用yum安装nc
//yum install -y nc
val lines: ReceiverInputDStream[String]= ssc.socketTextStream("192.168.174.100",8888)
//对DSteam进行操作,你操作这个抽象(代理,描述),就像操作一个本地的集合一样
//切分压平
val words: DStream[String] = lines.flatMap(_.split(" "))
//单词和一组合在一起
val wordAndOne: DStream[(String, Int)] = words.map((_,1))
val reduced: DStream[(String, Int)] = wordAndOne.reduceByKey(_+_)

//打印结果(Action)
reduced.print()
//启动sparksteaming程序
ssc.start()
//等待优雅的退出
ssc.awaitTermination()

DStream需要注意的点

  1. 检查点机制
    检查点机制是我们在 Spark Streaming 中用来保障容错性的主要机制。它可以使 SparkStreaming 阶段性地把应用数据存储到诸如 HDFS 这样的可靠存储系统中,以在发送失败时通过转换图的谱系图重算状态,并且提供驱动器程序容错。如果流计算应用中的驱动器程序崩溃了,你可以重启驱动器程序并让驱动器程序从检查点恢复, 这样 Spark Streaming 就可以读取之前运行的程序处理数据的进度,并从那里继续。
ssc.checkpoint("hdfs://...") 
  1. 驱动器程序容错
    驱动器程序的容错要求我们以特殊的方式创建 StreamingContext。我们需要把检查点目录提供给 StreamingContext。与 直接调用new StreamingContext不 同, 应 该 使 用StreamingContext.getOrCreate() 函数。
    驱动器程序失败之后,如果你重启驱动器程序并再次执行代码, getOrCreate() 会重新从检查点目录中初始化出StreamingContext,然后继续处理。
def createStreamingContext() = {
...
val sc = new SparkContext(conf)
// 以1秒作为批次大小创建StreamingContext
val ssc = new StreamingContext(sc, Seconds(1))
ssc.checkpoint(checkpointDir)
}
...
val ssc = StreamingContext.getOrCreate(checkpointDir, createStreamingContext _) 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值