Spark无状态和有状态转化操作介绍

1. 无状态转化操作

无状态转化操作就是把简单的RDD转化操作应用到每个批次上,也就是转化DStream中的每一个RDD。部分无状态转化操作列在了下表中。注意,针对键值对的DStream转化操作(比如 reduceByKey())要添加import StreamingContext._才能在Scala中使用

Spark无状态和有状态转化操作介绍_第1张图片
需要记住的是,尽管这些函数看起来像作用在整个流上一样,但事实上每个DStream在内部是由许多RDD(批次)组成,且无状态转化操作是分别应用到每个RDD上的。例如,reduceByKey()会归约每个时间区间中的数据,但不会归约不同区间之间的数据。

举个例子,在之前的wordcount程序中,我们只会统计5秒内接收到的数据的单词个数,而不会累加。

无状态转化操作也能在多个DStream间整合数据,不过也是在各个时间区间内。例如,键 值对DStream拥有和RDD一样的与连接相关的转化操作,也就是cogroup()、join()、leftOuterJoin() 等。我们可以在DStream上使用这些操作,这样就对每个批次分别执行了对应的RDD操作。
我们还可以像在常规的Spark 中一样使用 DStream的union() 操作将它和另一个DStream 的内容合并起来,也可以使用StreamingContext.union()来合并多个流。

2. 有状态转化操作:

2.1 DStream有状态操作之updateStateByKey操作

需求:实现跨批次之间维护状态(例如流计算中累加wordcount

在https://blog.csdn.net/qq_35885488/article/details/102667468基础上操作

先上代码

object UpdateStateByKey {
  def main(args: Array[String]): Unit = {
    System.setProperty("HADOOP_USER_NAME", "hadoop")
    var sparkConf =new SparkConf().setMaster("local[*]").setAppName("UpdateStateByKey").set("spark.testing.memory", "2147480000")
    
   //分析环境对象以及采集周期
    val streamContext = new StreamingContext(sparkConf,Seconds(10))
    //保存数据的状态,设置检查点路径
    streamContext.checkpoint("hdfs://192.168.181.110:9000/spark-streaming")
    //设置socket源
    val socketStreamLine: ReceiverInputDStream[String] = streamContext.socketTextStream("192.168.181.110",9999)
	
	//进行dstream操作,updateStateByKey实现了跨批次状态维护
    val print1: Unit = socketStreamLine.flatMap(_.split(" ")).map((_, 1))
      .updateStateByKey[Int](updateFunction _).print()

    //启动采集器
    streamContext.start()
    //等待采集器执行
    streamContext.awaitTermination()

  }

  /**
    *
    * @param currentValues
    * @param preValues
    * @return
    */
    //currentValues   preValues两个输入参数的数据来源是updateStateByKey[Int]
  def updateFunction(currentValues: Seq[Int], preValues: Option[Int]): Option[Int] = {
    val current = currentValues.sum
    val pre = preValues.getOrElse(0)
    Some(current + pre)
  }

}

代码核心1

//定义状态更新函数
def updateFunction(currentValues: Seq[Int], preValues: Option[Int]): Option[Int] = {
    val current = currentValues.sum
    val pre = preValues.getOrElse(0)

    Some(current + pre)
  }

核心二

	//设置检查点
    // 如果使用了stateful的算子,必须要设置checkpoint
    // 在生产环境中,建议大家把checkpoint设置到HDFS的某个文件夹中
    ssc.checkpoint("hdfs://192.168.181.110:9000/spark-streaming")

进行词频统计时,首先updateStateByKey操作会将当前批次到达的词频进行key相同的进行归并。

注意:设置检查点可能要修改文件夹权限hadoop fs -chmod -R 777 /dic
Spark无状态和有状态转化操作介绍_第2张图片
归并的规则
Spark无状态和有状态转化操作介绍_第3张图片

//currentValues: Seq[Int],====>(hadoop(1,1,1,1)),(spark(1,2,1))
// preValues: Option[Int] 维护当前历史状态的词频

updateFunction(currentValues: Seq[Int], preValues: Option[Int]): Option[Int]
val current = currentValues.sum  当前的数据求和操作

 val pre = preValues.getOrElse(0)   取历史,如果为空赋值为0

这里就不贴结果了,肯定能跑起来的…

完整代码托管于github地址:https://github.com/daizikaikou/learningSpark

你可能感兴趣的:(spark,Spark)