SparkStreaming02

1.transformation

(1)作用:用于DStream和RDD之间交互。

package SparkReview.Streaming02

import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}

import scala.collection.mutable.ListBuffer

object LeftJoinApp {
  def main(args: Array[String]): Unit = {
    val sparkConf=new SparkConf().setAppName("LeftJoinApp").setMaster("local[2]")
    val sc=new StreamingContext(sparkConf,Seconds(10))

    //TODO...从数据一(hdfs)上去读取日志信息,数据二为黑名单,俩份数据做join只要数据一中非黑名单的数据
    //数据一
    val input1=new ListBuffer[(String,Long)]
    input1.append(("www.ruozedata.com",9999))
    input1.append(("www.baidu.com",7777))
    input1.append(("www.ruozedata.com",77885))
    input1.append(("www.douyu.com",9999))
    input1.append(("www.baidu.com",6666))
    input1.append(("www.ruozedata.com",9999))
    val data1=sc.sparkContext.parallelize(input1)

    //数据二
    val input2=new ListBuffer[(String,Boolean)]
    input2.append(("www.baidu.com",true))
    val  data2=sc.sparkContext.parallelize(input2)
    data1.leftOuterJoin(data2).filter(x=>{
      x._2._2.getOrElse(false)!=true
    }).map(x=>(x._1,x._2._1)).collect().foreach(println)
    //做到这一步要注意他的数据结构了,这时候在根据下面这个数据类型做个过滤
    // (www.ruozedata.com,(9999,None))
    //(www.baidu.com,(7777,Some(true)))
    //过滤之后的数据结构变成了(www.douyu.com,(9999,None)),再做一次map

    sc.start()
    sc.awaitTermination()
  }
}

这是RDD和RDD之间的使用,上述需求如何用DStream完成呢?

package SparkReview.Streaming02

import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}

import scala.collection.mutable.ListBuffer

object LeftJoinStreamingApp {
  def main(args: Array[String]): Unit = {
    val sparkConf=new SparkConf().setMaster("local[2]").setAppName("LeftJoinStreamingApp")
    val ssc=new StreamingContext(sparkConf,Seconds(10))

    //数据二
    val input2=new ListBuffer[(String,Boolean)]
    input2.append(("wwww.baidu.com",true))
    val data2=ssc.sparkContext.parallelize(input2)


    //数据一
    val lines=ssc.socketTextStream("192.168.137.251",8888)
    lines.map(x=>(x.split(",")(0),x)).transform(rdd=>{//"wwww.baidu.com",("wwww.baidu.com",9999))
     rdd.leftOuterJoin(data2) //这里需要注意JVM编译是按照顺序来的,所以data2应该放在上面
      //数据结构为(wwww.baidu.com",("wwww.baidu.com",9999,Some(true)) (wwww.ruozedata.com",("wwww.ruozedata.com",8888,null))
        .filter(x=>{
       x._2._2.getOrElse(false)!=true
     }).map(x=>(x._2._1))
    }).print()



其实就是多了个transformation的操作





    ssc.start()
    ssc.awaitTermination()
  }
}
/*
object LeftJoinStreamingApp {

  def main(args: Array[String]) {
    val sparkConf = new SparkConf().setMaster("local[2]").setAppName("LeftJoinStreamingApp")
    val ssc = new StreamingContext(sparkConf, Seconds(30))

    // 数据二: rdd
    val input2 = new ListBuffer[(String,Boolean)]
    input2.append(("www.baidu.com",true))
    val data2 = ssc.sparkContext.parallelize(input2)

    // 数据一: nc过来
    val lines = ssc.socketTextStream("192.168.137.251",9888)
    lines.map(x=>(x.split(",")(0), x)).transform(rdd => {
      rdd.leftOuterJoin(data2).filter(x=>{
        x._2._2.getOrElse(false) != true
      }).map(_._2._1)
    }).print()

    ssc.start()
    ssc.awaitTermination()
  }

}
*/

2.foreachRDD和foreachPartition配合使用

(1)作用:当你处理完数据写入数据库的时候,就要用到这个俩了

import java.sql.DriverManager

import SparkReview.Streaming02.{BoneCPtest, ExampleJDBC}
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}


object ForeachRDDApp{
  def main(args: Array[String]): Unit = {
    val sparkConf=new SparkConf().setAppName("ForeachRDDApp").setMaster("local[2]")
    val ssc=new StreamingContext(sparkConf,Seconds(10))
    val lines=ssc.socketTextStream("192.168.137.251",8888)
    lines.flatMap(_.split(",")).map(x=>(x,1)).reduceByKey(_+_).foreachRDD(rdd=>{
      rdd.foreachPartition{x=>
        val connection=getConnection() //executed at the driver 这有个问题,假设有一百万条数据,
        // 岂不是要创建100万个链接?所以应该使用foreachpartition不用foreachrdd
        x.foreach(x=>{
          val word=x._1
          val count=x._2
          val sql=s"insert into wc(word,c) values('$word',$count)"
          connection.createStatement().execute(sql)

        })
        connection.close()

      }

    })
    ssc.start()
    ssc.awaitTermination()
  }
  def getConnection()={
    Class.forName("com.mysql.jdbc.Driver")
    DriverManager.getConnection("jdbc:mysql://192.168.137.251:3306/g3","root","123456")
  }
}

这里有个连接池的问题?记得实现!

3.Cache/persisit

(1)与rdd类似,DStreams还允许开发人员将流的数据持久化到内存中。也就是说,在DStream上使用persist()方法将自动将DStream的每个RDD持久化到内存中。如果DStream中的数据将被多次计算(例如,对同一数据的多个操作),那么这是非常有用的。对于基于窗口的操作(如reduceByWindow和reduceByKeyAndWindow)以及基于状态的操作(如updateStateByKey),这是隐式正确的。因此,由基于窗口的操作生成的DStreams将自动持久化到内存中,而无需开发人员调用persist()

长话短说就是它自己会自动persist不需要我们手工,在Dstream中不建议persisit,因为数据在不断的进来,一卡就延迟一堆。

4.Window operations

(1)使用场景:

  • window length - The duration of the window (3 in the figure).
  • sliding interval - The interval at which the window operation is performed (2 in the figure).

第一个时间称为窗口长度,第二个时间称为滑动长度,举例:其含义表示每隔4秒计算最近最近8秒的数据,这可以用于一些业务场景,例如网站记录,每隔1个小时计算最近两个小时的pv量,还有一种业务场景的话先在内存中做累加再更新到redis中做累加,比如说每隔5秒统计最近5秒的数据的总和,再刷到redis中做累加,因为频繁操作redis的话会存在问题.
(2)val ssc=new StreamingContext(sparkConf,Seconds(10))

此处设置的batch Interval是在spark streaming中生成基本Job的时间单位,窗口和滑动时间间隔一定是该batch Interval的整数倍,若要在内存中做简单的累加只要设置窗口长度和滑动长度相同即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值