spark streaming DStream算子大全

DStream作为spark 流处理的数据抽象,有三个主要的特征:

1.依赖的DStream的列表

2.DStream生成RDD的时间间隔

3.用来生成RDD的方法

本篇pom.xml文件spark streaming版本为1.6.0

目录

window()

reduceByWindow()

countByWindow()

countByValueAndWindow()

reduceByKeyAndWindow()

updatestateByKey()


window()

生成新的DStream

def window(windowDuration: Duration): DStream[T] = window(windowDuration, this.slideDuration)
def window(windowDuration: Duration, slideDuration: Duration): DStream[T] = ssc.withScope {
    new WindowedDStream(this, windowDuration, slideDuration)
 }

两个重载方法,第一个只传窗口长度(滑动间隔默认为实例化ssc时的时间间隔),第二个传窗口长度与滑动间隔

val ssc=new StreamingContext(sc,Seconds(1))//时间间隔为1s
val stream=xxxx //非重点,省略

stream.print()
stream.window(Seconds(4),Seconds(4)).print()
stream.window(Seconds(4),Seconds(5)).print()

第一次print():是每秒打印一次这1秒内接收的数据

第二次print():每4秒打印前4秒接收的数据

第三次print():每5秒打印最近4秒接收的数据 ,上个5秒间隔,第一秒内的数据不会打印

reduceByWindow()

生成新的DStream,作用于key-value类型

  def reduceByWindow(
      reduceFunc: (T, T) => T,
      windowDuration: Duration,
      slideDuration: Duration
    ): DStream[T] = ssc.withScope {
    this.reduce(reduceFunc).window(windowDuration, slideDuration).reduce(reduceFunc)
  }

需要传3个参数,依次为reduce()方法,窗口长度,滑动长度。

该方法的主要过程是:先将时间间隔内的数据调用reduce()算子聚合,然后调window()生成新的DStream,再将各间隔聚合完的结果聚合。

val ssc=new StreamingContext(sc,Seconds(1))//时间间隔
val stream=xxxx //类型为DStream[String]

stream.print()
stream.reduce((s1,s2)=>{
    s1+":"+s2
}).print()
stream.reduceByWindow((s1,s2)=>{
    s1+":"+s2
},Seconds(60),Seconds(10)).print()

第一次print():每秒打印一次接收的数据

第二次print():每秒打印一次,会将每秒接收到的数据拼接成起来

第三次print():每10秒打印一次,打印最近一分钟接收的数据,并拼接

countByWindow()

生成新的DStream

 def countByWindow(
      windowDuration: Duration,
      slideDuration: Duration): DStream[Long] = ssc.withScope {
    //reduceByWindow()第二各方法_+_为逆函数
    this.map(_ => 1L).reduceByWindow(_ + _, _ - _, windowDuration, slideDuration)
  }

需要两个参数,依次为:窗口长度,滑动间隔

该方法的主要过程为:先将每个元素生成长整数1,然后调用reduceByWindow()算子,将每个元素值相加。

val ssc=new StreamingContext(sc,Seconds(1))//时间间隔为1s
val stream=xxxx

stream.print()
stream.count().print()
stream.countByWindow(Seconds(10),Seconds(2)).print()

第一次print():每秒打印一次接收的数据

第二次print():每秒打印一次接收到元素的数量

第三次print():每2秒打印一次最近10秒接收到元素的数量

countByValueAndWindow()

生成新的DStream

   def countByValueAndWindow(
      windowDuration: Duration,
      slideDuration: Duration,
      numPartitions: Int = ssc.sc.defaultParallelism)
      (implicit ord: Ordering[T] = null)
      : DStream[(T, Long)] = ssc.withScope {
    this.map(x => (x, 1L)).reduceByKeyAndWindow(
      (x: Long, y: Long) => x + y,
      (x: Long, y: Long) => x - y,
      windowDuration,
      slideDuration,
      numPartitions,
      (x: (T, Long)) => x._2 != 0L
    )
  }

需要三个参数,依次为:窗口长度,滑动间隔,分区数(有默认值,可不传)

该方法的主要过程为:先将每个元素生成(元素,1L),然后调用reduceByKeyAndWindow(),可以理解为按key聚合,统计每个key的次数,也就是统计每个元素的次数

val ssc=new StreamingContext(sc,Seconds(1))
val stream=xxxx

stream.print()
stream.countByValue().print()
data.countByValueAndWindow(Seconds(10),Seconds(2)).print()

第一次print():每秒打印一次接收的数据

第二次print():每秒打印一次,会统计每个元素的次数  

第三次print():每2秒打印最近10秒的数据,统计每个元素次数

reduceByKeyAndWindow()

生成新的DStream

def reduceByKeyAndWindow(
      reduceFunc: (V, V) => V,
      windowDuration: Duration
    ): DStream[(K, V)] = ssc.withScope {
    reduceByKeyAndWindow(reduceFunc, windowDuration, self.slideDuration, defaultPartitioner())
  }

该方法有6个重载方法,就不一一粘了,参数为:聚合函数,窗口长度

该方法主要过程为:调reduceByKey()函数

val ssc=new StreamingContext(sc,Seconds(1))
val stream=xxxx  //stream类型为[String,Long]

stream.print()
data.reduceByKey((c1,c2)=>{
    c1+c2
  }).print()
data.reduceByKeyAndWindow((c1,c2)=>{
    c1+c2
  },Seconds(10)).print()

第一次print():每秒打印一次接收的数据

第二次print():每秒打印一次,计算每个key的次数

第三次print():每秒打印一次最近10秒每个key的次数

updatestateByKey()

生成新的DStream

所有的window操作都是计算长度为窗口长度的数据,非window操作都是计算设置的时间间隔内的数据,而updateBykey可以理解成在无限长的时间里,为每个key保存一个状态,这个时间长度可以通过ssc.awaitTerminationOrTimeout()来控制,一般来说长度每天或每小时。

def updateStateByKey[S: ClassTag](
      updateFunc: (Seq[V], Option[S]) => Option[S]
    ): DStream[(K, S)] = ssc.withScope {
    updateStateByKey(updateFunc, defaultPartitioner())
  }

当然,该方法重载方法也6个,这里只讨论上面的,传入一个更新方法,该方法两个参数:一个为当前时间间隔内数据,类型为Seq,一个为之前的数据,可能无数据(第一次提交计算的时候),类型为Option,返回值也为Option类型

下面是两个实例,求pv和uv

//pv
val stream=xxxx//类型得转化为[当前日期,1L]
stream.updateStateByKey((curvalues:Seq[Long],prevalue:Option[Long])=>{
      val sum=curvalues.sum
      val pre=prevalue.getOrElse(0L)
      Some(sum+pre)
    })
//uv   因为uv涉及到去重,故将userid放入Set里
val stream=xxxx //类型为[当前日期,userid]
stream.updateStateByKey((curvalues:Seq[Set[String]],prevalue:Option[Set[String]])=>{
      var curs=Set[String]()
      if(!curvalues.isEmpty){
        curs=curvalues.reduce(_++_)//将两个Set集合合并
      }
      Some(curs++prevalue.getOrElse(Set[String]()))
    })

未完待续。。。。

猜你喜欢

转载自blog.csdn.net/zhaolq1024/article/details/83749026