• SparkStreaming基础案例


    WordCount案例

    案例一:

    import org.apache.spark.streaming._

    val ssc = new StreamingContext(sc,Seconds(5));

    val lines = ssc.textFileStream("file:///home/software/stream");

    //val lines = ssc.textFileStream("hdfs://hadoop01:9000/wordcount");

    val words = lines.flatMap(_.split(" "));

    val wordCounts = words.map((_,1)).reduceByKey(_+_);

    wordCounts.print();

    ssc.start();

       

    基本概念

    1. StreamingContext

    StreamingContext是Spark Streaming编程的最基本环境对象,就像Spark编程中的SparkContext一样。StreamingContext提供最基本的功能入口,包括从各途径创建最基本的对象DStream(就像Spark编程中的RDD)。

       

    创建StreamingContext的方法很简单,生成一个SparkConf实例,设置程序名,指定运行周期(示例中是5秒),这样就可以了:

    val conf = new SparkConf().setAppName("SparkStreamingWordCount")

    val sc=new SparkContext(conf)

    val ssc = new StreamingContext(sc, Seconds(5))

    运行周期为5秒,表示流式计算每间隔5秒执行一次。这个时间的设置需要综合考虑程序的延时需求和集群的工作负

    载,应该大于每次的运行时间。

       

    StreamingContext还可以从一个现存的org.apache.spark.SparkContext创建而来,并保持关联,比如上面示例中的创建方法:

    val ssc = new StreamingContext(sc, Seconds(5))

       

    StreamingContext创建好之后,还需要下面这几步来实现一个完整的Spark流式计算:

    (1)创建一个输入DStream,用于接收数据;

    (2)使用作用于DStream上的TransformationOutput操作来定义流式计算(Spark程序是使用Transformation和Action操作);

    (3)启动计算,使用streamingContext.start();

    (4)等待计算结束(人为或错误),使用streamingContext.awaitTermination();

    (5)也可以手工结束计算,使用streamingContext.stop()。

       

    2. DStream抽象

    DStream(discretized stream)是Spark Streaming的核心抽象,类似于RDD在Spark编程中的地位。DStream表示连续的数据流,要么是从数据源接收到的输入数据流,要求是经过计算产生的新数据流。DStream的内部是一个RDD序列,每个RDD对应一个计算周期。比如,在上面的WordCount示例中,每5秒一个周期,那么每5秒的数据都分别对应一个RDD,如图所示,图中的时间点1、2、3、4代表连续的时间周期。

       

       

    所有应用在DStream上的操作,都会被映射为对DStream内部的RDD上的操作,比如上面的WordCount示例中对lines DStream的flatMap操作,如下图

       

       

    RDD操作将由Spark核心来调度执行,但DStream屏蔽了这些细节,给开发者更简洁的编程体验。当然,我们也可以直接对DStream内部的RDD进行操作(后面会讲到)。

       

       

    案例二:

    经过测试,案例一代码确实可以监控指定的文件夹处理其中产生的新的文件

    但数据在每个新的周期到来后,都会重新进行计算

    如果需要对历史数据进行累计处理 该怎么做呢

    SparkStreaming提供了checkPoint机制,首先需要设置一个检查点目录,在这个目录,存储了历史周期数据。通过在临时文件中存储中间数据 为历史数据累计处理提供了可能性

       

    import org.apache.spark.streaming._

    val ssc = new StreamingContext(sc,Seconds(5));

    ssc.checkpoint("file:///home/software/chk");

    val lines = ssc.textFileStream("file:///home/software/stream");

    val result= lines.flatMap(_.split(" ")).map((_,1)).updateStateByKey{(seq, op:Option[Int]) =>

    { Some(seq.sum +op.getOrElse(0)) }}

    result.print();

    ssc.start();

       

       

    updateStateByKey 方法说明:

    1.seq:是一个序列,存的是某个key的历史数据

    2.op:是一个值,是某个key当前的值

    比如: (hello,1)

    ①seq里是空的,Some(1)=>Some(返回的是历史值的和+当前值)

    (hello,2),seq(1) op=2 Some(1+2)

    (hello,1) , seq(1,2) op=1 Some(3+1)

       

       

       

    案例三:

    但是这上面的例子里所有的数据不停的累计 一直累计下去

    很多的时候我们要的也不是这样的效果 我们希望能够每隔一段时间重新统计下一段时间的数据,并且能够对设置的批时间进行更细粒度的控制,这样的功能可以通过滑动窗口的方式来实现。

    DStream中提供了如下的和滑动窗口相关的方法:

    window(windowLength, slideInterval)

    windowLength:窗口长度

    slideInterval:滑动区间

    countByWindow(windowLength, slideInterval)

    reduceByWindow(func, windowLength, slideInterval)

    reduceByKeyAndWindow(func, windowLength, slideInterval, [numTasks])

    reduceByKeyAndWindow(func, invFunc, windowLength, slideInterval, [numTasks])

    countByValueAndWindow(windowLength, slideInterval, [numTasks])

       

    可以通过以上机制改造案例

    import org.apache.spark.streaming._

    val ssc = new StreamingContext(sc,Seconds(1));

    ssc.checkpoint("file:///home/software/chk");

    val lines = ssc.textFileStream("file:///home/software/stream");

    val result = lines.flatMap(_.split(" ")).map((_,1)).reduceByKeyAndWindow((x:Int,y:Int)=>x+y, Seconds(5), Seconds(5) ).print()

    ssc.start();

       

    注意:窗口长度和滑动长度必须是batch size的整数倍

    此外,使用窗口机制,必须要设定检查点目录

  • 相关阅读:
    2019年4月18日 查询功能 2
    bzoj3601
    bzoj2693
    bzoj2440
    bzoj3529
    bzoj2820
    BZOJ2813
    BZOJ4515
    AtCoder Grand Contest 001 题解
    BZOJ2757
  • 原文地址:https://www.cnblogs.com/shuzhiwei/p/11323137.html
Copyright © 2020-2023  润新知