Structured Streaming利用withWatermark和window窗口函数实现wordcount

Structured Streaming利用withWatermark和window窗口函数实现WordCount

  • pom添加依赖
<dependencies>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_2.11</artifactId>
            <version>2.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>2.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql-kafka-0-10_2.11</artifactId>
            <version>2.2.0</version>
        </dependency>
</dependencies>
package com.test

import java.sql.Timestamp
import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, SparkSession}
import org.apache.spark.sql.functions.window
import org.apache.spark.sql.streaming.Trigger

object StructureStreaming_new4 {
    def main(args: Array[String]): Unit = {
      //    spark配置对象
      val sparkConf = new SparkConf().setMaster("local[*]").setAppName("StructureStreamin_WordCount")
      //创建 sparkSession对象
      val spark = SparkSession.builder().config(sparkConf).getOrCreate()
      val df:DataFrame= spark.readStream
        .format("kafka")//指定从kafka读取数据-----可以从包括Kafka、Flume、以及TCP socket等
        .option("kafka.bootstrap.servers","10.21.13.181:9092") //指定kafka对应的节点
        .option("subscribe","first") //订阅first主题
        .option("includeTimestamp", true)//输出内容包括时间戳
        .load()
    //    默认内存表df含有如下字段   
    //    key binary
    //    value binary
    //    topic string
    //    partition int
    //    offset long
    //    timestamp long
    //    timestampType int
      import spark.implicits._
      val words = df.selectExpr("key","value","timestamp").as[(String, String,Timestamp)]
      
      //      Event time 事件时间: 就是数据真正发生的时间,比如用户浏览了一个页面可能会产生一条用户的该时间点的浏览日志。        
      //      Process time 处理时间: 则是这条日志数据真正到达计算框架中被处理的时间点,简单的说,就是你的Spark程序是什么时候读到这条日志的。
      
      val wordCounts = words.toDF("key", "value","timestamp")
        .withWatermark("timestamp","2 minutes").groupBy(
        //.withWatermark("timestamp","2 minutes") 第一个参数是事件时间,第二个参数是延迟的时间阈值
        window($"timestamp", "2 minutes","1 minutes"), $"value"
        //第二个参数是窗口长度,第三个参数是滑动间隔
      ).count()
        //.selectExpr("CAST(value AS STRING)","count")
        .selectExpr( "window","CAST(value AS STRING)","count")
       //selectExpr("CAST(value AS STRING)"的结果,value是字节数组,所以,执行CAST的作用是将value转换为字符串
         .orderBy("window")

      val query = wordCounts.writeStream
        .outputMode("complete")
        //    Append模式:只有自上次触发后在Result Table表中附加的新行将被写入外部存储器。重点模式,一般使用它。
        //Sorting is not supported on streaming DataFrames/Datasets,
        //    Complete模式: 将整个更新表写入到外部存储。每次batch触发计算,整张Result Table的结果都会被写出到外部存储介质。
        //    Update模式:只有自上次触发后在Result Table表中更新的行将被写入外部存储器。注意,这与完全模式不同,因为此模式不输出未更改的行。
        .format("console")//以控制台形式输出
        .option("truncate", "false")//指定"truncate"只是为了在控制台输出时,不进行列宽度自动缩小。
      //kafka输出
      //        .format("kafka")
      //        .option("kafka.bootstrap.servers","10.21.13.181:9092")
      //        .option("topic","first")
      //        .option("checkpointLocation", "D:\\tmp")

        //.trigger(Trigger.ProcessingTime(180)) //触发器 -- 三分钟执行一次结果输出
        //  window($"timestamp", "2 minutes","1 minutes") 如果不加trigger那么默认一分钟输出一个结果
        //  如果加了trigger那么三分钟才会输出一次结果
        .start()

      query.awaitTermination()
  }
}

  • 开启kafka Producer
kafka-console-producer.sh --broker-list dn1:9092 --topic first
  • 输入数据
    在这里插入图片描述
  • 输出结果
+---------------------------------------------+-----+-----+
|window                                       |value|count|
+---------------------------------------------+-----+-----+
|[2020-06-30 12:28:00.0,2020-06-30 12:30:00.0]|dog  |2    |
|[2020-06-30 12:28:00.0,2020-06-30 12:30:00.0]|cat  |3    |
|[2020-06-30 12:29:00.0,2020-06-30 12:31:00.0]|cat  |3    |
|[2020-06-30 12:29:00.0,2020-06-30 12:31:00.0]|dog  |2    |
+---------------------------------------------+-----+-----+
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值