版权申明:转载请注明出处。
文章来源:bigdataer.net

1.什么是spark-streaming?

实际生产中会有许多应用到实时处理的场景,比如:实时监测页面点击,实时监测系统异常,实时监测来自于外部的攻击。针对这些场景,twitter研发了实时数据处理工具storm,并在后来开源。spark针对这些场景设计了spark-streaming实时计算模型,它允许用户使用一系列批处理的API去处理实时数据,能做到代码逻辑的重复使用。
和spark中的rdd非常相似,spark-streaming中使用离散化流(discretized stream)作为抽象的表示,叫做DStream。它是随时间推移而收集数据的序列,每个时间段收集到的数据在DStream内部以一个RDD的形式存在。DStream支持从kafka,flume,hdfs,s3等获取输入。DStream也支持两种操作,即转化操作和输出操作(区别于RDD中的行动操作)。转化操作又分为无状态的转化操作和有状态的转化操作,无状态的转化操作有map,filter,flatmap,repartition等,是针对单个时间区间内的操作。而有状态的转化操作可以针对不同的时间区间,后面详述。

2.两个简单的例子

2.1 监听socket获取数据,代码如下:
这里使用nc -lk 9999 在ip为10.121.33.44的机器上发送消息

scala    17行

object SocketStream {
def main(args: Array[String]): Unit = {
//本地测试,设置4核
val conf = new SparkConf().setMaster("local[4]").setAppName("streaming")
//以10秒为一个批次
val ssc = new StreamingContext(conf,Seconds(10))
//接收消息
val dstream = ssc.socketTextStream("10.121.33.44",9999,StorageLevel.MEMORY_AND_DISK_SER)
//监测关键字error,出现则print
dstream.filter(_.contains("error")).foreachRDD(rdd=>{
rdd.foreach(println(_))
})
ssc.start()
ssc.awaitTermination()
}
}

2.2 从kafka读取数据,比较常用

scala    31行

object KafkaStream {

  def main(args: Array[String]): Unit = {
//本地测试,设置4核
val conf = new SparkConf().setMaster("local[4]").setAppName("streaming")
//以10秒为一个批次
val ssc = new StreamingContext(conf,Seconds(10)) val zkQuorum = "10.22.33.44:6688,10.22.33.45:6688/kafka_cluster"
val group_id = "realtime_data" //kafka相关参数
val kafka_param = Map[String,String](
"zookeeper.connect" ->zkQuorum,
"group.id" -> group_id,
"zookeeper.connection.timeout.ms" -> "10000",
"fetch.message.max.bytes" -> "10485760"
)
val topic = Map[String,Int]("test_topic" -> 16)
//接收消息
val dstream = KafkaUtils.createStream[String,String,StringDecoder,StringDecoder](ssc,kafka_param,topic,StorageLevel.MEMORY_AND_DISK_SER).map(_._2)
//监测关键字error,出现则print
dstream.filter(_.contains("error")).foreachRDD(rdd=>{
rdd.foreach(println(_))
}) ssc.start()
ssc.awaitTermination()
}
}

3.再来谈架构

通过上面两个例子,你可能对spark-streaming有了初步的了解,我们再来看一下它的架构。
Spark-streaming使用"微批次"的架构,把流式计算当做一系列微型的批处理操作来对待,每个时间段都产生一个RDD。如图:

作用于一个DStream上的无状态转化操作会对它其中的每个RDD生效,如针对一个输入为语句的DStream做flatMap操作的示意图如下:

4.转化操作

4.1 无状态的转化操作。
无状态转化操作就是简单的将转化作用于DStream的每个RDD上面。下面列举了一些常见的转化操作,其中最后一个transform表示可以试用自定义的转化函数,尽管它前面已经提供了很多现成的API。

4.2有状态的转化操作。
有状态的转化操作是跨时间段的数据操作,一些先前的批次也被用来在新的批次中做计算。主要有滑动窗口和updateStateByKey。前者以一个时间段为滑动窗口进行操作,后者则用来跟踪每个键的状态变化。有状态的转化操作需要打开检查点机制来保证容错性。即:给ssc.checkpoint()设置一个检查点目录。
(1)基于窗口的转化操作会在一个比ssc设置的更长的时间段内,通过整合多个批次的,计算出整个大的时间窗口的结果。基于窗口的操作需要两个参数,一个是窗口时长,一个是滑动步长。这两个参数是ssc设置的时长的整数倍。下面的图表示了一个时间窗口为3,滑动步长为2的窗口转化操作。

前面提到的监测关键字error的例子,现在需要每隔20s就对前面30s有error的日志记录做计数,代码如下:

scala    34行

object KafkaStream {

  def main(args: Array[String]): Unit = {
//本地测试,设置4核
val conf = new SparkConf().setMaster("local[4]").setAppName("streaming")
//以10秒为一个批次
val ssc = new StreamingContext(conf,Seconds(10)) val zkQuorum = "10.22.33.44:6688,10.22.33.45:6688/kafka_cluster"
val group_id = "realtime_data" //kafka相关参数
val kafka_param = Map[String,String](
"zookeeper.connect" ->zkQuorum,
"group.id" -> group_id,
"zookeeper.connection.timeout.ms" -> "10000",
"fetch.message.max.bytes" -> "10485760"
)
val topic = Map[String,Int]("test_topic" -> 16)
//接收消息
val dstream = KafkaUtils.createStream[String,String,StringDecoder,StringDecoder](ssc,kafka_param,topic,StorageLevel.MEMORY_AND_DISK_SER)
.map(_._2)
//每隔20s对前30s出现error的日志做计数
val errors = dstream.window(Seconds(30),Seconds(20))
.filter(_.contains("error"))
.count()
errors.foreachRDD(rdd=>{
rdd.foreach(println(_))
})
ssc.start()
ssc.awaitTermination()
}
}

(2)updateStateByKey
updateStateByKey能对键值对的数据进行不同批次间的数据计算,使用updateStateByKey,需要传入一个update函数,这个函数接收某个key最新批次对应的values,以及该key之前对应的value,按照自定义的逻辑返回一个新的value。如需要计算一个实时日志中http响应码的计数,代码如下:

scala    39行

object KafkaStream {

  def main(args: Array[String]): Unit = {
//输出目录
val output = args(0)
//本地测试,设置4核
val conf = new SparkConf().setMaster("local[4]").setAppName("streaming")
//以10秒为一个批次
val ssc = new StreamingContext(conf,Seconds(10)) val zkQuorum = "10.22.33.44:6688,10.22.33.45:6688/kafka_cluster"
val group_id = "realtime_data" //kafka相关参数
val kafka_param = Map[String,String](
"zookeeper.connect" ->zkQuorum,
"group.id" -> group_id,
"zookeeper.connection.timeout.ms" -> "10000",
"fetch.message.max.bytes" -> "10485760"
)
val topic = Map[String,Int]("test_topic" -> 16)
//接收消息
val dstream = KafkaUtils.createStream[String,String,StringDecoder,StringDecoder](ssc,kafka_param,topic,StorageLevel.MEMORY_AND_DISK_SER).map(_._2)
val rdd = dstream.map(_.split("\001"))
.map(x=>(x(0),x(1).toLong))
.updateStateByKey(update)
//输出
rdd.foreachRDD(_.saveAsTextFile(output))
ssc.start()
ssc.awaitTermination()
}
//update函数
def update(new_values:Seq[Long],old_value:Option[Long]):Option[Long]={
val current_num = new_values.size
val result_num = current_num + old_value.getOrElse(0L)
Some(result_num)
}
}

(3)所有有状态转化操作

5.输出操作

输出操作比较简单,有以下几种:

6.作业稳定性

spark-streaming作业一般都要全天候不间断运行,那么作业的稳定性如何保证?主要有以下几点:
6.1 检查点机制。
其原理就是阶段性的将作业运行的数据存放到存储系统,如hdfs,s3等。当作业运行出现异常时可以从上述数据中恢复。
6.2 驱动器容错。
在创建实时计算作业的上下文时使用getOrCreate函数。代码如下:

scala    7行

	val ssc = StreamingContext.getOrCreate(cp_dir,createContext )
def createContext(): StreamingContext ={
val sc = new SparkContext(conf)
val ssc = new StreamingContext(sc,Seconds(10))
ssc.checkpoint(cp_dir)
}

更多文章请关注微信公众号:bigdataer

一篇文章学会spark-streaming的更多相关文章

  1. 【干货】一篇文章学会Gulp(Getting started with Gulp)

    抛开Grunt,又有一个新的自动化构建系统成为新的领跑者.那就是Gulp. Gulp是一种直观.自动化构建的工具. 为什么前端er会这么感兴趣Gulp?我相信大家都有个思想:要么不做事,要做事就要把事 ...

  2. 一篇文章学会Spring4.0

    spring概述 spring 是一个开源框架. Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能. Spring 是 ...

  3. 一篇文章学会springMVC(转)

    说在前面 本文只是入门 为什么用springMVC?springMVC有什么有缺点?springMVC和Struts有什么区别?等等这些问题可以参考网路上资源,本文的重点是快速带入,让大家了解熟悉sp ...

  4. 一篇文章学会shell工具篇之sed

    sed工具执行原理; 有关sed的参数及action的常见操作方法; 定址; 模式空间和保持空间; 使用标签 1.首先先来了解一下什么是sed? sed叫做流编辑器,在shell脚本和Makefile ...

  5. 一篇文章学会Docker命令

    目录 简介 镜像仓库 login pull push search 本地镜像管理 images rmi tag build history save load import 容器操作 ps inspe ...

  6. 一篇文章学会shell脚本

    一.Shell传递参数 #!/bin/bash # 假设在脚本运行时写了三个参数 ..,,则 "(传递了三个参数). echo "-- \$* 演示 --" for i ...

  7. 大数据技术之_19_Spark学习_04_Spark Streaming 应用解析 + Spark Streaming 概述、运行、解析 + DStream 的输入、转换、输出 + 优化

    第1章 Spark Streaming 概述1.1 什么是 Spark Streaming1.2 为什么要学习 Spark Streaming1.3 Spark 与 Storm 的对比第2章 运行 S ...

  8. 【慕课网实战】Spark Streaming实时流处理项目实战笔记十之铭文升级版

    铭文一级: 第八章:Spark Streaming进阶与案例实战 updateStateByKey算子需求:统计到目前为止累积出现的单词的个数(需要保持住以前的状态) java.lang.Illega ...

  9. 【慕课网实战】Spark Streaming实时流处理项目实战笔记九之铭文升级版

    铭文一级: 核心概念:StreamingContext def this(sparkContext: SparkContext, batchDuration: Duration) = { this(s ...

随机推荐

  1. 面试STAR法则

    昨天投了几家公司的简历,A公司还没看简历,B公司没有通过简历,另外的后说(其实只投了这两家),B公司最终给了蛮中肯的回复: 虽然,一开始看到这样的结果,有些失落,仔细看过回复后,有些不屑和好奇.百度了 ...

  2. AngularJS 讲解,三 过滤器

    过滤器用来格式化需要展示给用户的数据.AngularJS有很多实用的内置过滤器,同时也提供了方便的途径可以自己创建过滤器. 在HTML中的模板绑定符号{{ }}内通过|符号来调用过滤器.例如:{{va ...

  3. java was started but returned exit code=1

    将eclipse.ini文件删掉, 重启eclipse 会自动生成一个eclipse.ini就可以了~

  4. 创建超小的Golang docker 镜像

    原文: http://colobu.com/2015/10/12/create-minimal-golang-docker-images/ 本文对于创建超小的镜像非常有用 Docker是PaaS供应商 ...

  5. Exchange 2016 系统要求

    Exchange 2016 和早期版本的 Exchange Server 共存方案 Exchange 2016支持混合部署方案 Exchange 2016 的网络和目录服务器要求 目录服务体系结构: ...

  6. SpringMVC 之 RESTful 风格的增删改查

    1. 视图和视图解析器 视图解析器 请求处理方法执行完成后,最终返回一个ModelAndView对象,对于返回String,View 或 ModelMap 等类型的处理方法, SpringMVC 也会 ...

  7. JS产品分类列表练习

    CSS: ;;} ul,li{list-style: none;} body{color: #666;background: #f5f5f5;} a{text-decoration: none;col ...

  8. 《深入理解Linux网络技术内幕》阅读笔记 --- 路由基本概念

    一.路由的基本概念 1.一条路由就是一组参数,这些参数存储了往一个给定目的地转发流量所需的信息,而一条路由所需的最少的参数集合为:(1)目的网络,(2)出口设备,(3)下一跳网关 2.路由中的相关术语 ...

  9. Python--(并发编程之线程Part2)

    GIL只能保证垃圾回收机制的安全,进程中的数据安全还是需要自定义锁 线程执行代码首先要抢到GIL全局锁,假设线程X首先抢到,以为要抢到自定义锁要执行代码,所以这个线程在执行代码的时候就很容抢到了自定义 ...

  10. MyBatis缓存机制-二级缓存

    MyBatis二级缓存是基于namespace级别的缓存. 1.MyBatis的缓存机制整体设计以及二级缓存的工作模式 如上图所示,当开一个会话时,一个SqlSession对象会使用一个Executo ...