8.4.Spark Streamng入门

python编程快速上手(持续更新中…)

推荐系统基础


1、SparkStreaming概述

1.1 SparkStreaming是什么

  • 可扩展,高吞吐具有容错性的流式计算框架

对比常用实时计算/流式计算框

  • Storm流式计算
    • 来一条处理一条
    • 对比:速度更快
    • 对python不友好
  • Flink流式计算
    • 来一条处理一条
    • 对比:速度更快
  • SparkStreaming实时(准时的)
    • Mirco batch
    • 指定一个时间间隔
    • 间隔一段时间,获取一次数据
    • 能处理数据量大
    • 实时性差点
    • pyspark

1.2 SparkStreaming的组件

  • Streaming Context

    • 流的上线文,通过Streaming Context可以连接数据源获取数据
    • 通过Spark Context可以获取到Streaming Context
    • 在创建Streaming Context需要指定一个时间间隔(micro batch)
    • Streaming Context调用了stop方法之后 就不能再次调 start()
    • 一个SparkContext创建一个Streaming Context
    • Streaming Context上调用Stop方法, 也会关闭SparkContext对象, 如果只想仅关闭Streaming Context对象,设置stop()的可选参数为false
    • 对DSream种的数据出来的逻辑要卸载StreamingContext开启之前,一旦StreamingContext调用了start方法,就不能再添加新的逻辑出来
  • DStream

    • Streaming Context连接到不同的数据源获取的数据,抽象成DStream模型
    • 代表一个连续的数据流
    • 由一系列连续的RDD组成
    • 任何对DStreams的操作都转换成了对DStreams隐含的RDD的操作
  • DStreams中的每个RDD都包含确定时间间隔内的数据

    • 数据源
      • 基本源
        • TCP/IP Socket
        • FileSystem
      • 高级源
        • Kafka
        • Flume

2、Spark Streaming编码实践

  • Spark Streaming编码步骤:
    • 1,创建一个StreamingContext
    • 2,从StreamingContext中创建一个数据对象DStream
    • 3,对数据对象进行Transformations操作
    • 4,输出结果
    • 5,开始和停止

2.1利用Spark Streaming实现WordCount

需求:监听某个端口上的网络数据,实时统计出现的不同单词个数。

1,需要安装一个nc工具:

sudo yum install -y nc

2,执行指令:

nc -lk 9999 -v

3,代码如下
import os
# 配置spark driver和pyspark运行时,所使用的python解释器路径
PYSPARK_PYTHON = "/miniconda2/envs/py365/bin/python"
JAVA_HOME='/root/bigdata/jdk'
SPARK_HOME = "/root/bigdata/spark"
# 当存在多个版本时,不指定很可能会导致出错
os.environ["PYSPARK_PYTHON"] = PYSPARK_PYTHON
os.environ["PYSPARK_DRIVER_PYTHON"] = PYSPARK_PYTHON
os.environ['JAVA_HOME']=JAVA_HOME
os.environ["SPARK_HOME"] = SPARK_HOME
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
if __name__ == "__main__":

    sc = SparkContext("local[2]",appName="NetworkWordCount")
    #参数2:指定执行计算的时间间隔
    ssc = StreamingContext(sc, 1)
    #监听ip,端口上的上的数据
    lines = ssc.socketTextStream('localhost',9999)
    #将数据按空格进行拆分为多个单词
    words = lines.flatMap(lambda line: line.split(" "))
    #将单词转换为(单词,1)的形式
    pairs = words.map(lambda word:(word,1))
    #统计单词个数
    wordCounts = pairs.reduceByKey(lambda x,y:x+y)
    #打印结果信息,会使得前面的transformation操作执行
    wordCounts.pprint()
    #启动StreamingContext
    ssc.start()
    #等待计算结束
    ssc.awaitTermination()
4,可视化查看效果:http://192.168.19.137:4040

点击streaming,查看效果

3、Spark Streaming的状态操作

  • 在Spark Streaming中存在两种状态操作
    • UpdateStateByKey
    • Windows操作
  • 使用有状态的transformation,需要开启Checkpoint
    • spark streaming 的容错机制
    • 它将足够多的信息checkpoint到某些具备容错性的存储系统如hdfs上,以便出错时能够迅速恢复

3.1 updateStateByKey

Spark Streaming实现的是一个实时批处理操作,每隔一段时间将数据进行打包,封装成RDD,是无状态的。
无状态:指的是每个时间片段的数据之间是没有关联的。

需求:想要将一个大时间段(1天),即多个小时间段的数据内的数据持续进行累积操作
一般超过一天都是用RDD或Spark SQL来进行离线批处理
如果没有UpdateStateByKey,我们需要将每一秒的数据计算好放入mysql中取,再用mysql来进行统计计算
Spark Streaming中提供这种状态保护机制,即updateStateByKey

步骤

  • 首先,要定义一个state,可以是任意的数据类型
  • 其次,要定义state更新函数–指定一个函数如何使用之前的state和新值来更新state
  • 对于每个batch,Spark都会为每个之前已经存在的key去应用一次state更新函数,无论这个key在batch中是否有新的数据。如果state更新函数返回none,那么key对应的state就会被删除
  • 对于每个新出现的key,也会执行state更新函数
案例:监听网络端口的数据,获取到每个批次的出现的单词数量,并且需要把每个批次的信息保留下来

updateStateByKey

import os
# 配置spark driver和pyspark运行时,所使用的python解释器路径
PYSPARK_PYTHON = "/miniconda2/envs/py365/bin/python"
JAVA_HOME='/root/bigdata/jdk'
SPARK_HOME = "/root/bigdata/spark"
# 当存在多个版本时,不指定很可能会导致出错
os.environ["PYSPARK_PYTHON"] = PYSPARK_PYTHON
os.environ["PYSPARK_DRIVER_PYTHON"] = PYSPARK_PYTHON
os.environ['JAVA_HOME']=JAVA_HOME
os.environ["SPARK_HOME"] = SPARK_HOMEfrom pyspark.streaming import StreamingContextfrom pyspark.sql.session import SparkSession
# 创建SparkContext
spark = SparkSession.builder.master("local[2]").getOrCreate()
sc = spark.sparkContext

ssc = StreamingContext(sc, 3)
#开启检查点
ssc.checkpoint("checkpoint")
#定义state更新函数
def updateFunc(new_values, last_sum):
    return sum(new_values) + (last_sum or 0)

lines = ssc.socketTextStream("localhost", 9999)
# 对数据以空格进行拆分,分为多个单词
counts = lines.flatMap(lambda line: line.split(" ")) \
    .map(lambda word: (word, 1)) \
.updateStateByKey(updateFunc=updateFunc)
#应用updateStateByKey函数

counts.pprint()

ssc.start()
ssc.awaitTermination()
总结

在这里插入图片描述

3.2 Windows

  • 窗口长度L:运算的数据量
  • 滑动间隔G:控制每隔多长时间做一次运算

每隔G秒,统计最近L秒的数据
在这里插入图片描述
操作细节

  • Window操作是基于窗口长度和滑动间隔来工作的
  • 窗口的长度控制考虑前几批次数据量
  • 默认为批处理的滑动间隔来确定计算结果的频率

相关函数
在这里插入图片描述

  • Smart computation

  • invAddFunc

  • reduceByKeyAndWindow(func,invFunc,windowLength,slideInterval,[num,Tasks])

    • func:正向操作,类似于updateStateByKey
    • invFunc:反向操作

例如在热词时,在上一个窗口中可能是热词,这个一个窗口中可能不是热词,就需要在这个窗口中把该次剔除掉
典型案例:热点搜索词滑动统计,每隔10秒,统计最近60秒钟的搜索词的搜索频次,并打印出最靠前的3个搜索词出现次数。
在这里插入图片描述

案例:监听网络端口的数据,每隔3秒统计前6秒出现的单词数量
import os
# 配置spark driver和pyspark运行时,所使用的python解释器路径
PYSPARK_PYTHON = "/miniconda2/envs/py365/bin/python"
JAVA_HOME='/root/bigdata/jdk'
SPARK_HOME = "/root/bigdata/spark"
# 当存在多个版本时,不指定很可能会导致出错
os.environ["PYSPARK_PYTHON"] = PYSPARK_PYTHON
os.environ["PYSPARK_DRIVER_PYTHON"] = PYSPARK_PYTHON
os.environ['JAVA_HOME']=JAVA_HOME
os.environ["SPARK_HOME"] = SPARK_HOME
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
from pyspark.sql.session import SparkSession

def get_countryname(line):
    country_name = line.strip()

    if country_name == 'usa':
        output = 'USA'
    elif country_name == 'ind':
        output = 'India'
    elif country_name == 'aus':
        output = 'Australia'
    else:
        output = 'Unknown'

    return (output, 1)
if __name__ == "__main__":
    #定义处理的时间间隔
    batch_interval = 1 # base time unit (in seconds)
    #定义窗口长度
    window_length = 6 * batch_interval
    #定义滑动时间间隔
    frequency = 3 * batch_interval

    #获取StreamingContext
    spark = SparkSession.builder.master("local[2]").getOrCreate()
    sc = spark.sparkContext
    ssc = StreamingContext(sc, batch_interval)

    #需要设置检查点
    ssc.checkpoint("checkpoint")

    lines = ssc.socketTextStream('localhost', 9999)
    addFunc = lambda x, y: x + y
    invAddFunc = lambda x, y: x - y
    #调用reduceByKeyAndWindow,来进行窗口函数的调用
    window_counts = lines.map(get_countryname) \
        .reduceByKeyAndWindow(addFunc, invAddFunc, window_length, frequency)
    #输出处理结果信息
    window_counts.pprint()

    ssc.start()
    ssc.awaitTermination()
总结

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值