[TOC]
DStream的各种transformation
Transformation Meaning
map(func) 对DStream中的各个元素进行func函数操作,然后返回一个新的DStream.
flatMap(func) 与map方法类似,只不过各个输入项可以被输出为零个或多个输出项
filter(func) 过滤出所有函数func返回值为true的DStream元素并返回一个新的DStream
repartition(numPartitions) 增加或减少DStream中的分区数,从而改变DStream的并行度
union(otherStream) 将源DStream和输入参数为otherDStream的元素合并,并返回一个新的DStream.
count() 通过对DStreaim中的各个RDD中的元素进行计数,然后返回只有一个元素的RDD构成的DStream
reduce(func) 对源DStream中的各个RDD中的元素利用func进行聚合操作,然后返回只有一个元素的RDD构成的新的DStream.
countByValue() 对于元素类型为K的DStream,返回一个元素为(K,Long)键值对形式的新的DStream,Long对应的值为源DStream中各个RDD的key出现的次数
reduceByKey(func, [numTasks]) 利用func函数对源DStream中的key进行聚合操作,然后返回新的(K,V)对构成的DStream
join(otherStream, [numTasks]) 输入为(K,V)、(K,W)类型的DStream,返回一个新的(K,(V,W)类型的DStream
cogroup(otherStream, [numTasks]) 输入为(K,V)、(K,W)类型的DStream,返回一个新的 (K, Seq[V], Seq[W]) 元组类型的DStream
transform(func) 通过RDD-to-RDD函数作用于源码DStream中的各个RDD,可以是任意的RDD操作,从而返回一个新的RDD
updateStateByKey(func) 根据于key的前置状态和key的新值,对key进行更新,返回一个新状态的Dstream
Window 函数:
可以看到很多都是在RDD中已经有的transformation算子操作,所以这里只关注transform、updateStateByKey和window函数
transformation之transform操作
DStream transform
1、transform操作,应用在DStream上时,可以用于执行任意的RDD到RDD的转换操作。它可以用于实现,DStream API中所没有提供的操作。比如说,DStream API中,并没有提供将一个DStream中的每个batch,与一个特定的RDD进行join的操作。但是我们自己就可以使用transform操作来实现该功能。
2、DStream.join(),只能join其他DStream。在DStream每个batch的RDD计算出来之后,会去跟其他DStream的RDD进行join。
案例
测试代码如下:
package cn.xpleaf.bigdata.spark.scala.streaming.p1
import org.apache.log4j.{Level, Logger}
import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
/**
* 使用Transformation之transform来完成在线黑名单过滤
* 需求:
* 将日志数据中来自于ip["27.19.74.143", "110.52.250.126"]实时过滤掉
* 数据格式
* 27.19.74.143##2016-05-30 17:38:20##GET /static/image/common/faq.gif HTTP/1.1##200##1127
*/
object _06SparkStreamingTransformOps {
def main(args: Array[String]): Unit = {
if (args == null || args.length < 2) {
System.err.println(
"""Parameter Errors! Usage:
|hostname: 监听的网络socket的主机名或ip地址
|port: 监听的网络socket的端口
""".stripMargin)
System.exit(-1)
}
Logger.getLogger("org.apache.spark").setLevel(Level.OFF)
val conf = new SparkConf()
.setAppName(_01SparkStreamingNetWorkOps.getClass.getSimpleName)
.setMaster("local[2]")
val ssc = new StreamingContext(conf, Seconds(2))
val hostname = args(0).trim
val port = args(1).trim.toInt
//黑名单数据
val blacklist = List(("27.19.74.143", true), ("110.52.250.126", true))
// val blacklist = List("27.19.74.143", "110.52.250.126")
val blacklistRDD:RDD[(String, Boolean)] = ssc.sparkContext.parallelize(blacklist)
val linesDStream:ReceiverInputDStream[String] = ssc.socketTextStream(hostname, port)
// 如果用到一个DStream和rdd进行操作,无法使用dstream直接操作,只能使用transform来进行操作
val filteredDStream:DStream[String] = linesDStream.transform(rdd => {
val ip2InfoRDD:RDD[(String, String)] = rdd.map{line => {
(line.split("##")(0), line)
}}
/** A(M) B(N)两张表:
* across join
* 交叉连接,没有on条件的连接