Spark的API操作

1)转换算子

**加粗**的都是常用的,希望可以帮助到大家!!
  • Map(fun):对源Rdd的函数操作应用返回一个新的RDD map((word,1)) map(t2=>(t2,1))
  • Filter(fun):对源rdd****的元素进行过滤,保留符合条件的元素返回一个新的rdd 列:* filter(t2 => ! t2._1.equals(“b”))
  • flatMap**(fun):rdd****的元素展开为(0-n)的元素,并返回一个新的rdd。**flatMap(line => line.split(" "))
  • mapProtitions****(func):都源rdd的每一个分区** 独立应用的函数,返回一个新的****rdd
  • mapPartitionsWithIndex(func) : 对源RDD的每一个分区应用函数操作,注意携带分区的索引序号,并返回一个新的RDD
  • sample(withreplacement(是否允许重复),fraction(分数,每个数据被抽中的概率),seef(种子,用于底层产生的随机数字)):数据取样采样方法
  • union(rdd):将源rdd和新的rdd的数据合并,产生新的rdd
  • intersection(rdd):将源rdd和新的rdd的数据做交集,产生新的rdd
  • distinct([numpartition]):对源rdd进行元素的去重,是宽依赖
  • groupbykey([numpartition]):对源rdd【k,v】进行调用,产生新的rdd[k,v(iteator)](key相同)
  • reducebykey(fun,[numpartition]):对一个源rdd《k,v》进行调用,返回一个新的rdd
  • aggregatebykey(zeroValue)(seqOp, combOp, [numPartitions]) 注意:首先分区内的计算,其次分区间的计算。
  • sortByKey([ascending], [numPartitions]) : 对源RDD(k,v)调用,根据k进行排序返回一个新的RDD
  • sortBy:(可以选择建或值,false,1):降序为false 升序为true
  • **Join:**两个RDD(K,V)和(K,W)进行连接操作,返回一个新的RDD(K,(V,W))left join、right join
  • cogroup(otherDataset, [numPartitions]:共同分组,两个RDD(K,V)和(K,W)进行共同分组,返回一个新的RDD (K, (Iterable, Iterable))
  • cartesian(笛卡尔连接):所有的都享用
  • pipe(command, [envVars]) : 不是很重要,在RDD的每一个分区执行一个Shell指令或者脚本
  • coalesce(numPartitions) : 将源RDD的分区数量减少为numPartitions返回一个新的RDD :注意,如果子类分区量超过父rdd的分区量时,按父rdd的分区量进行计算
  • repartition(numPartitions) : 重新分区 stage (TaskSet) --> Task :Partition —> Task:Thread
  • repartitionAndSortWithinPartitions(partitioner): 重新分区,并对分区内的数据进行局部排序

2) 行动算子

  1. reduce:对rdd中的元素进行操作
  2. collect() : 收集方法,将RDD的所有元素以数组形式返回给Driver端 。mkstring()
  3. count() : 返回RDD中元素的个数
  4. first() : 返回RDD中的第一个元素
  5. take(n) : 返回RDD中的前N个元素, 排行榜
  6. takeSample(withReplacement, num, [seed]) : 数据采样
  7. saveAsTextFile(path) : 将RDD中的内容保存到HDFS或者Local File System
  8. saveAsSequenceFile(path): 将RDD的内容以序列化文件的形式保存在HDFS或者Local FileSystem
  9. countByKey(): 统计相同key的value数量,返回HashMap

SparkStreaming的API操作

1)转换算子

  • 有几个转换算子与SparkApi的功能相同,大家可以对照上面来进行操作和学习.(map,flatmap,repartion,filter)
  • union :将两个DStream组合在一起返回一个新的DStream
  • count:返回未批Rdd中元素的个数
  • reduce :对DStream每一个元素应用函数进行计算 可以在reduce简写 reduce(+
  • countByValue : 对DStream调用 返回DStream相同元素k的出现count (k,count)
  • reduceByKey: 根据key应用计算函数
  • join :两个DStream进行连接操作 一般都用于(流+批)操作
  • cogroup:共同分组,将两个未批RDD进行分组
  • transform 对DStream的每一个微批RDD 应用RDD操作,并且返回一个新的DStream 【非常重点】

对于这个是流处理中很重要的一个api操作,在这里给大家举一个实例来梳理:

特点: 将DStream转换为RDD,应用RDD的操作 // 例子:

如有某系统实现抽奖功能, 但是系统黑名单的用户不允许参与抽奖
    //    1. 非法的用户 加入系统黑名单【用户名、IP】
    //    2. 抽奖请求(正常用户 + 黑名单用户)
    //       流(抽奖请求) + 批(黑名单)
	val conf=new Sparkconf().appName("reduce").Master("local[*]")
    val ssc=new StreamingContext(conf,Seconds(5))//5秒处理一个微批RDD
	val ds12 = ssc.socketTextStream("SparkOnStandalone", 9999);

    val blacklist = List((1, "zs"), (2, "ww"), (3, "tq"))
    val blacklistRDD = ssc.sparkContext.makeRDD(blacklist)

    // 流格式:userid method url
    ds12
      .map(request => {
        val arr = request.split(" ")
        val userId: Int = arr(0).toInt
        val method: String = arr(1)
        val url: String = arr(2)
        (userId, (method, url))
      })
      .transform(streamRDD => { // 流 --> 流RDD.leftOuterJoin(批RDD)
        streamRDD.leftOuterJoin(blacklistRDD)
      })
      // 最终仅保留 白名单用户  黑名单用户: (1,((GET,/xxx),Some(zs)))
      //                     白名单用户: (4,((DELETE,/xxx2),None))
      .filter(t2 => t2._2._2.isEmpty) // 是不是为空?
      .map(t2 => (t2._1, t2._2._1._1, t2._2._1._2))
      .print()


    //4. 启动流应用
    ssc.start()

    //5. 优雅的关闭应用
    ssc.awaitTermination()
  }
}
  • updateStateByKey**(func) :根据key更新状态数据。
  • mapWithState:与上面功能相同。都是 更新状态数据
  • 相同点:updateStateByKey和mapWithState 用来进行有状态操作相关的转换算子
  • 不同点:
  • updateStateByKey 将key相同的一组数据,应用状态更新操作;而mapWithState 对每一条数据应用状态更新操作
  • updateStateByKey 状态数据全量操作,而mapWithState 状态数据增量操作
  • 效率:mapWithState 更高效的状态更新操作,建议使用

2)行动算子

  • print :打印Dstream(微批RDD)的前十行数据
  • saveAsTextFiles(prefix, [suffix]):以文本文件的形式保存结果 ,参数指定前缀和后缀(它没有指定path,保存到应用的运行目录当中)
  • saveAsObjectFiles**(prefix, [suffix]):以序列化的形式保存结果。指定前缀和后缀
  • saveAsHadoopFiles**(prefix, [suffix]):以hadoop的文件形式存储,指定前缀和后缀
  • foreachRDD**(func) 【重点】:对每一个DStream的微批Rdd应用foreach操作
.foreachRDD(rdd => { // 列举一个将计算结果写到redis中
        rdd.foreachPartition(itar => {
          val jedisPool = new JedisPool("SparkOnStandalone", 6379)
          while (itar.hasNext) {
            val element = itar.next()
            val jedis = jedisPool.getResource
            jedis.set(element._1, element._2.toString)
            jedisPool.returnResource(jedis)
          }
        })
      })

流数据的窗口计算API操作

再写API操作前,先给大家说一说窗口的概念,可以更好的理解API操作

窗口:有界有范围的流数据

拆分条件:大小+时间

翻滚窗口:窗口大小固定,数据无重合

spark null字段 spark numpartitions_spark null字段

滑动(跳跃)窗口:窗口大小固定,数据有重合

spark null字段 spark numpartitions_ide_02

这几个图片有助于大家更好的理解 翻滚和滑动

  • window**(windowLength, slideInterval):设置窗口的时长

.window(Seconds(60))

countByWindow(windowLength, slideInterval):统计每个窗口中元素的个数

.countByWindow(Seconds(10), Seconds(10))

  • reduceByWindow**(func, windowLength, slideInterval):将窗口中的数据进行聚合(计算)操作

.reduceByWindow(_ * _, Seconds(10), Seconds(10))

  • reduceByKeyAndWindow**(func, windowLength, slideInterval, [numTasks]):将窗口中的函数按照key,进行reduce函数计算

.reduceByKeyAndWindow((v1: Int, v2: Int) => v1 + v2, Seconds(10), Seconds(10))

  • reduceByKeyAndWindow**(func, invFunc, windowLength, slideInterval, [numTasks]):更高效的reduce计算

.reduceByKeyAndWindow((v1: Int, v2: Int) => v1 + v2, (v1: Int, v2: Int) => v1 - v2, Seconds(5), Seconds(2))

  • countByValueAndWindow**(windowLength, slideInterval, [numTasks]):对相同key的值,进行value的累加

.countByValueAndWindow(Seconds(5),Seconds(5))

v1 + v2, (v1: Int, v2: Int) => v1 - v2, Seconds(5), Seconds(2))

  • countByValueAndWindow**(windowLength, slideInterval, [numTasks]):对相同key的值,进行value的累加

.countByValueAndWindow(Seconds(5),Seconds(5))