Spark Streaming状态管理函数(三)——MapWithState的使用(scala版)

MapWithState

  关于mapWithState

  注意事项

  示例代码

  运行

  结论

  

关于mapWithState

  需要自己写一个匿名函数func来实现自己想要的功能。如果有初始化的值得需要,可以使用initialState(RDD)来初始化key的值。 另外,还可以指定timeout函数,该函数的作用是,如果一个key超过timeout设定的时间没有更新值,那么这个key将会失效。这个控制需要在func中实现,必须使用state.isTimingOut()来判断失效的key值。如果在失效时间之后,这个key又有新的值了,则会重新计算。如果没有使用isTimingOut,则会报错。

注意事项

  下面程序是使用idea编写的,使用的是scala语言,在程序中master(“local[2]”)设置为本地模式([]中的数指定的是线程数,不能少于2,否则看不到结果。主要是因为spark需要启动一个线程receiver来循环接收数据,一个Executor来接收数据,如果少于2线程不够将不能打印出结果。),在window上运行的。使用的spark版本是2.3.0,在2.x以后的版本,基本采用SparkSession来进行操作。同时,想要运行程序你的服务器上还必须要安装netcat这个软件,使用yum install nc进行安装(注意安全配置好yum源,DNS才能下载安装),使用命令nc -lk 6666开启服务发送数据。最后在运行程序前还需要导入spark、scala相应的依赖包。

示例代码
package spark2x

import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming.dstream.{DStream, MapWithStateDStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Seconds, State, StateSpec, StreamingContext}

/**
  * 类名  MapWithState
  * 作者   彭三青
  * 创建时间  2018-12-01 14:08
  * 版本  1.0
  * 描述: $
  */

object MapWithState {
  // 设置本地运行模式
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder()
      .master("local[2]")
      .appName("MapWithState")
      .getOrCreate()

    // 创建一个context,批次间隔为2秒钟,
    val ssc: StreamingContext = new StreamingContext(spark.sparkContext, Seconds(3))

    // 设置checkpoint目录
    ssc.checkpoint("hdfs://SC01:8020/user/tmp/cp-20181201-2")

    // 创建一个ReceiverInputDStream,从服务器端的netcat接收数据。
    // 服务器主机名SC01(SC01已在Window上的hosts文件中做了映射,没做映射的则写ip就OK了),监听端口为6666
    val line: ReceiverInputDStream[String] = ssc.socketTextStream("SC01", 6666)

    // 对接收到的数据进行处理,进行切割,分组形式为(day, 1) (word 1)
    val wordsStream: DStream[(String, Int)] = line.flatMap(_.split(" ")).map((_, 1))

    val wordCount: MapWithStateDStream[String, Int, Int, Any] = wordsStream.mapWithState(StateSpec.function(func).timeout(Seconds(30)))

	// 打印
    wordCount.print()
	// 提交
    ssc.start()
	// 
    ssc.awaitTermination()
  }

  /**
    * 定义一个函数,该函数有三个类型word: String, option: Option[Int], state: State[Int]
    * 其中word代表统计的单词,option代表的是历史数据,state代表的是返回的状态
    */
  val func = (word: String, option: Option[Int], state: State[Int]) => {
    if(state.isTimingOut()){
      println(word + "is timeout")
    }else{
      // 获取历史数据,当前值加上上一个批次的该状态的值
      val sum = option.getOrElse(0) + state.getOption().getOrElse(0)
      // 单词和该单词出现的频率
      val wordFreq = (word, sum)
      // 更新状态
      state.update(sum)
      wordFreq
    }
  }
}
运行

  服务器运行nc
在这里插入图片描述
  idea端运行编写好的程序
  服务器发送数据
在这里插入图片描述
  控制台显示结果
在这里插入图片描述

结论

  mapWithState它会按照时间线在每一个批次间隔返回之前的发生改变的或者新的key的状态,不发生变化的不返回。同时mapWithState可以不用设置checkpoint,返回的数据量少,性能和效率都比mapWithState好。




第一篇:Spark Streaming状态管理函数(一)——updateStateByKey和mapWithState
第二篇:Spark Streaming状态管理函数(二)——updateStateByKey的使用(scala版)

猜你喜欢

转载自blog.csdn.net/m0_37914799/article/details/84703854
今日推荐