DStream 其实是 RDD 的序列,它的语法与 RDD 类似,分为 transformation(转换) 和 output(输出) 两种操作;

DStream 的转换操作分为 无状态转换 和 有状态转换,且 tansformation 也是惰性的;

DStream 的输出操作请参考 我的博客 Streaming

无状态转换

转换操作只作用于单个 RDD,即单个数据流的 batch;

例如,每次根据采集到的数据流统计单词个数,第一次采集到的是  a 2个 b 1个,第二次采集到的是 a 1个 b 1个,那么第二次的输出也是 a 1 b 1,并不与前面的累计

DStream 的转换操作最终还是会转化成 RDD 的转换操作,这个转化由 spark streaming 完成

本文只介绍部分 API,详细请参考源码 /usr/lib/spark/python/pyspark/streaming/dstream.py

基本转换

为了解释下面的操作,假定输入都一样,如下

  1. hellp spark
  2. hello hadoop hive

map(self, f, preservesPartitioning=False):生成一个新的 DStream,不解释了

  1. [u'hellp', u'spark']
  2. [u'hello', u'hadoop', u'hive']

flatMap(self, f, preservesPartitioning=False):把一个 func 作用于 DStream 的所有元素,并将生成的结果展开

  1. hellp
  2. spark
  3. hello
  4. hadoop
  5. hive

filter(self, f):不解释了

repartition(self, numPartitions):把 DStream 中每个 RDD 进行分区,用于提高并发

union(self, other):在一个 RDD 上再加一个 RDD

聚合转换

count(self):

reduce(self, func):

countByValue(self):返回一个由键值对型 RDD 构成的 DStream

  1. # 输入
  2. a
  3. a
  4. b
  5. # 输出
  6. (u'a', 2)
  7. (u'b', 1)

键值对转换

cogroup(self, other, numPartitions=None):把两个 kv 构成的 DStream 根据 key 进行合并,注意是取 key 的并集

  1. sc = SparkContext()
  2.  
  3. ssc = StreamingContext(sc, 30)
  4. line1 = ssc.socketTextStream('192.168.10.11', 9999)
  5. out1 = line1.map(lambda x: (len(x), x)).groupByKey() # value 没有进行任何操作
  6. out1.pprint()
  7.  
  8. line2 = ssc.socketTextStream('192.168.10.11', 9998)
  9. out2 = line2.map(lambda x: (len(x), x)).groupByKey()
  10. out2.pprint()
  11.  
  12. out3 = out1.cogroup(out2)
  13. out3.pprint()
  14.  
  15. ssc.start()
  16. ssc.awaitTermination()

很遗憾,合并之后,value 是个对象集,不可见

join(self, other, numPartitions=None):把两个 kv 构成的 DStream 连接起来

如 (K,V) 构成的 DStream 和 (K,W) 构成的 DStream 连接后是 (K, (V,W))

同样有 左连接、右连接、全连接

  1. out3 = out1.join(out2) # 内连接 二者都有
  2. out3 = out1.leftOuterJoin(out2) # 左连接 左边有,找对应右边的
  3. out3 = out1.rightOuterJoin(out2) # 右连接 右边有,找对应左边的
  4. out3 = out1.fullOuterJoin(out2) # 全连接 笛卡尔内积

reduceByKey(self, func, numPartitions=None):

groupByKey(self, numPartitions=None):将构成 DStream 的 RDD 中的元素进行 分组

还有很多,不一一解释了,记住本质,这些虽然是 DStream 的 API,但是这些 API 其实是作用于 构成 DStream 的 RDD 上的

transform:这个比较特殊

  1. transform(self, func):
  2. """
  3. Return a new DStream in which each RDD is generated by applying a function
  4. on each RDD of this DStream.
  5.  
  6. `func` can have one argument of `rdd`, or have two arguments of
  7. (`time`, `rdd`)
  8. """

输入一个 函数,这个函数作用于 构成 DStream 的每个 RDD ,并返回新的 RDD ,重新构成一个 DStream

transform 用于 机器学习 或者 图计算 时优势明显

示例

  1. from pyspark import SparkContext
  2. from pyspark.streaming import StreamingContext
  3.  
  4. sc = SparkContext()
  5. ssc = StreamingContext(sc, 20)
  6. line1 = ssc.socketTextStream('192.168.10.11', 9999)
  7. out1 = line1.map(lambda x: (len(x), x))
  8. ### 输入为
  9. # a
  10. # aaa
  11. # aa
  12. out1.pprint()
  13. # (1, u'a')
  14. # (3, u'aaa')
  15. # (2, u'aa') 这是一个 RDD,被 transform 的 func 作用
  16.  
  17. out2 = out1.transform(lambda x: x.sortByKey())
  18. out2.pprint()
  19. # (1, u'a')
  20. # (2, u'aa')
  21. # (3, u'aaa')
  22.  
  23. out3 = out1.transform(lambda x: x.mapValues(lambda m: ''))
  24. out3.pprint()
  25.  
  26. ssc.start()
  27. ssc.awaitTermination()

有状态转换

转换操作作用于之前所有的 RDD 上

例如,每次根据采集到的数据流统计单词个数,第一次采集到的是  a 2个 b 1个,第二次采集到的是 a 1个 b 1个,那么第二次的输出也是 a 3 b 2,累计之前的

updateStateByKey(self, updateFunc, numPartitions=None, initialRDD=None):更新当前 RDD 的状态,不好解释,用例子帮助理解

需要设置检查点, 用于保存状态

示例

  1. from pyspark import SparkContext
  2. from pyspark.streaming import StreamingContext
  3.  
  4. def updateFunction(newValues, runningCount):
  5. if runningCount is None:
  6. runningCount = 0
  7. return sum(newValues, runningCount) # add the new values with the previous running count to get the new count
  8.  
  9. sc = SparkContext()
  10. ssc = StreamingContext(sc, 20)
  11. ssc.checkpoint('/usr/lib/spark') # 必须有检查点
  12.  
  13. line1 = ssc.socketTextStream('192.168.10.11', 9999)
  14. out1 = line1.map(lambda x: (x, 1)).reduceByKey(lambda x, y: x + y) # 对当前 RDD 的处理
  15.  
  16. runningCounts = out1.updateStateByKey(updateFunction) # 更新状态
  17. runningCounts.pprint()
  18.  
  19. ssc.start()
  20. ssc.awaitTermination()

示例操作

由于统计全局,所以需要checkpoint数据会占用较大的存储。而且效率也不高。所以很多时候不建议使用updateStateByKey

窗口操作

updateStateByKey 也是一种窗口,只是窗口大小不固定;

这里的窗口就是指滑窗,跟 均值滤波里面的滑窗意思一样;

这里的滑窗内的元素是 RDD;

滑窗有 窗口尺寸 和 滑动步长 两个概念

滑窗也是有状态的转换

这里的 尺寸 和 步长 都是用时间来描述;

尺寸 是 采集周期的 N 倍,步长 也是 采集周期的 N 倍;

window(self, windowDuration, slideDuration=None):windowDuration 为 窗口时长,slideDuration 为步长

示例

  1. from pyspark import SparkContext
  2. from pyspark.streaming import StreamingContext
  3.  
  4. sc = SparkContext()
  5. ssc = StreamingContext(sc, 20)
  6. line1 = ssc.socketTextStream('192.168.10.11', 9999)
  7.  
  8. ## 先处理再滑窗
  9. out1 = line1.map(lambda x: (len(x), x))
  10. out2 = out1.window(40)
  11. # out2 = out2.groupByKey() # 滑窗后可继续处理
  12. out2.pprint()
  13.  
  14. ssc.start()
  15. ssc.awaitTermination()

示例操作

可以看到有重复计算的内容

reduceByWindow(self, reduceFunc, invReduceFunc, windowDuration, slideDuration):当 slideDuration < windowDuration 时,计算是有重复的,那么我们可以不用重新获取或者计算,而是通过获取旧信息来更新新的信息,这样可以提高效率

函数解释

window 计算方式如下===

win1 = time1 + time2 + time3

win2 = time3 + time4 + time5

显然 time3 被重复获取并计算

reduceByWindow 计算方式如下====

win1 = time1 + time2 + time3

win2 = win1 + time4 + time5 -time1 -time2

reduceFunc 是对新产生的数据(time4,time5) 进行计算;

invReduceFunc 是对之前的旧数据(time1,time3) 进行计算;

示例

  1. from pyspark import SparkContext
  2. from pyspark.streaming import StreamingContext
  3.  
  4. def func1(x, y):
  5. return x+y
  6.  
  7. def func2(x, y):
  8. return -x-y
  9.  
  10. sc = SparkContext(appName="windowStream", master="local[*]")
  11. # 第二个参数指统计多长时间的数据
  12. ssc = StreamingContext(sc, 10)
  13. ssc.checkpoint("/tmp/window")
  14. lines = ssc.socketTextStream('192.168.10.11', 9999)
  15. # 第一个参数执行指定函数, 第二个参数是窗口长度, 第三个参数是滑动间隔
  16. lines = lines.flatMap(lambda x: x.split(' ')).map(lambda x: (x, 1))
  17. dstream = lines.reduceByWindow(func1, func2, 20, 10)
  18. dstream.pprint()
  19.  
  20. ssc.start()
  21. ssc.awaitTermination()

reduceByWindow 和 window 可实现相同效果;

reduceByWindow 的底层是 reduceByKeyAndWindow,用法也完全相同,reduceByKeyAndWindow 的效率更高

需要设置检查点, 用于保存状态

reduceByKeyAndWindow(self, func, invFunc, windowDuration, slideDuration=None,
numPartitions=None, filterFunc=None):与 reduceByWindow 的区别是 它的输入需要 kv 对

  1. dstream = lines.reduceByKeyAndWindow(func1, func2, 20, 10)

countByWindow(self, windowDuration, slideDuration):计数

需要设置检查点, 用于保存状态

示例

  1. sc = SparkContext()
  2. ssc = StreamingContext(sc, 20)
  3. line1 = ssc.socketTextStream('192.168.10.11', 9999)
  4.  
  5. ssc.checkpoint('/usr/lib/spark')
  6.  
  7. ## 先处理再滑窗
  8. out1 = line1.map(lambda x: x)
  9. out2 = out1.countByWindow(40, 20)
  10. # out2 = out2.groupByKey() # 滑窗后可继续处理
  11. out2.pprint()
  12.  
  13. ssc.start()
  14. ssc.awaitTermination()

countByValueAndWindow(self, windowDuration, slideDuration, numPartitions=None):

groupByKeyAndWindow(self, windowDuration, slideDuration, numPartitions=None):

不一一解释了

总结

1. 凡是带 key 的都需要输入 kv 对

2. 凡是需要记录上个 状态的 都需要设置检查点

参考资料:

《Spark大数据分析核心概念技术及实践OCR-2017》 电子书

https://www.cnblogs.com/libin2015/p/6841177.html

spark教程(16)-Streaming 之 DStream 详解的更多相关文章

  1. Spark小课堂Week6 启动日志详解

    Spark小课堂Week6 启动日志详解 作为分布式系统,Spark程序是非常难以使用传统方法来进行调试的,所以我们主要的武器是日志,今天会对启动日志进行一下详解. 日志详解 今天主要遍历下Strea ...

  2. 16个PHP设计模式详解

    说明:该教程全部截选自实验楼教程[16个PHP设计模式详解]:主要介绍16个常用的设计模式的基础概念和技术要点,通过UML类图帮助理解设计模式中各个类之间的关联关系,针对每种设计模式都使用PHP完成了 ...

  3. ASP.NET MVC 5 学习教程:生成的代码详解

    原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...

  4. PHP 中 16 个魔术方法详解

    PHP 中 16 个魔术方法详解   前言 PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用. 魔术方法包括: __constru ...

  5. 《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(5)-Fiddler监控面板详解

    1.简介 按照从上往下,从左往右的计划,今天就轮到介绍和分享Fiddler的监控面板了.监控面板主要是一些辅助标签工具栏.有了这些就会让你的会话请求和响应时刻处监控中毫无隐私可言.监控面板是fiddl ...

  6. Python学习入门教程,字符串函数扩充详解

    因有用户反映,在基础文章对字符串函数的讲解太过少,故写一篇文章详细讲解一下常用字符串函数.本文章是对:程序员带你十天快速入门Python,玩转电脑软件开发(三)中字符串函数的详解与扩充. 如果您想学习 ...

  7. Cobalt Strike系列教程第二章:Beacon详解

    上周更新了Cobalt Strike系列教程第一章:简介与安装,文章发布后,深受大家的喜爱,遂将该系列教程的其他章节与大家分享,提升更多实用技能! 第二章:Beacon详解 一.Beacon命令 大家 ...

  8. 《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(6)-Fiddler状态面板详解

    1.简介 按照从上往下,从左往右的计划,今天就轮到介绍和分享Fiddler的状态面板了. 2.状态面板概览 Fiddler的状态面板概览,如下图所示: 3.状态面板详解 Fiddler底端状态栏面板详 ...

  9. spark教程(15)-Streaming

    Spark Streaming 是一个分布式数据流处理框架,它可以近乎实时的处理流数据,它易编程,可以处理大量数据,并且能把实时数据与历史数据结合起来处理. Streaming 使得 spark 具有 ...

随机推荐

  1. Leetcode题目94.二叉树的中序遍历(中等)

    题目描述: 给定一个二叉树,返回它的中序遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 思路解析: 1 ...

  2. Linux设备驱动程序 之 顺序锁

    当要保护的资源很小,很简单,会频繁的被访问而且写入访问很少的且必须快速时(即读不允许让写饥饿),就可以使用顺序锁(seqlock):从本质上讲,顺序锁会允许读取者对资源的自由访问,但需要读取者检查是否 ...

  3. iSCSI存储技术

    iSCSI(Internet Small Computer System Interface),Internet小型计算机系统接口,又称为IP-SAN,是一种基于因特网及SCSI-3协议下的存储技术, ...

  4. JS 省市联动 ajax

    省市联动 //省市联动     $('.locationCode').change(function () {         var val = $(this).val();         if ...

  5. 图解Python 【第八篇】:网络编程-进程、线程和协程

    本节内容一览图: 本章内容: 同步和异步 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 一.同步和异步 你叫我去吃饭 ...

  6. 升级到Android Studio3.x遇到的问题及解决方案

    升级到Android Studio3.x遇到的问题及解决方案 转 https://www.2cto.com/kf/201711/695736.html 升级到Android Studio3.0遇到的问 ...

  7. Jmeter联机负载时报错: connection refused to host localhost,nested exception is:java.net ConnectException:Connection refused:connect

    Jmeter联机负载时报错: connection refused to host localhost,nested exception  is:java.net ConnectException:C ...

  8. WPF 绑定集合 根据集合个数改变样式 INotifyCollectionChanged

    问题:当前ListBox Items 绑定 集合数据源ListA时候:ListA集合数据源中存在另外一个集合ListB,当更改或往ListB集合中添加数据的时候,通知改变? 实体类继承 INotify ...

  9. WebServer_简单例子

    #-*-coding:utf-8-*- importwebimportjson urls=("/.*","index")app=web.application( ...

  10. [CDH] Redis: Remote Dictionary Server

    基本概念 一.安装 Redis: Remote Dictionary Server 远程字典服务 使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种 ...