SparkStreaming算子分为两类:transformation算子和outputOperator算子
transformation算子:flatMap、count、mapToPair、map、countByValue、repartition、filter、join、union、Reduce、reduceByKey、updataStateByKey、Window、transformoutputOperator算子:print、foreachRDD、saveAsTextFile、saveAsHadoopFile、saveAsObjectFile
1、outputoperator类的算子
print:显示DStream结果
foreachRDD:可以遍历DStream中的RDD,对RDD使用RDD的算子去转换,一定要有RDD的action类算子触发RDD的transformation类算子执行
foreachRDD中除了RDD算子之内的代码在Executor中执行,其他在Driver端执行,可以在foreachRDD中动态改变广播变量的值,因为每隔batchInterval会执行foreachRDD中的代码一次 。
saveAsTextFile
saveAsHadoopFile
saveAsObjectFile
可以触发transformation类算子去执行,可以拿到SparkStreaming中的RDD进行处理
foreachRDD算子 注意:
- foreachRDD是DStream中outputoperator类算子
- foreachRDD可以遍历得到DStream中的RDD,可以在这个算子内对RDD使用RDD的Transformation类算子进行转换,但是一定要使用RDD的Action类算子触发执行
- foreachRDD可以得到DStream中的RDD,在这个算子内,RDD算子外执行的代码是在Driver端执行的,RDD算子内的代码是在Driver端执行的
counts.foreachRDD(new VoidFunction<JavaPairRDD<String,Integer>>() {
private static final long serialVersionUID = 1L;
@Override
public void call(JavaPairRDD<String, Integer> arg0)
throws Exception {
System.out.println("*****************");
//转换为RDD,需要Action算子触发
JavaRDD<String> maprdd = arg0.map(new Function<Tuple2<String,Integer>, String>() {
private static final long serialVersionUID = 1L;
@Override
public String call(Tuple2<String, Integer> arg0)
throws Exception {
//这个里面在Executor端执行,外面在Driver端执行,包括上一层的call方法也是在Driver端执行
System.out.println("--------------");
return arg0._1+"---"+arg0._2;
}
});
maprdd.collect();
}
});
2、transformation算子
updateStateByKey算子
/**
* UpdateStateByKey的主要功能:
* 1、为Spark Streaming中每一个Key维护一份state状态,state类型可以是任意类型的, 可以是一个自定义的对象,那么更新函数也可以是自定义的。
* 2、通过更新函数对该key的状态不断更新,对于每个新的batch而言,Spark Streaming会在使用updateStateByKey的时候为已经存在的key进行state的状态更新
*
* hello,3
* bjsxt,2
*
* 如果要不断的更新每个key的state,就一定涉及到了状态的保存和容错,这个时候就需要开启checkpoint机制和功能
*
* 全面的广告点击分析
* @author root
*
* 有何用? 统计广告点击流量,统计这一天的车流量,统计点击量
*/
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local[2]").setAppName("UpdateStateByKeyDemo");
JavaStreamingContext jsc = new JavaStreamingContext(conf, Durations.seconds(5));
/**
* 设置checkpoint目录
*
* 多久会将内存中的数据(每一个key所对应的状态)写入到磁盘上一份呢?
* 如果你的batch interval小于10s 那么10s会将内存中的数据写入到磁盘一份
* 如果bacth interval 大于10s,那么就以bacth interval为准
*
* 这样做是为了防止频繁的写HDFS
*/
// jsc.checkpoint("hdfs://node1:9000/spark/checkpoint");
jsc.checkpoint("./checkpoint");
JavaReceiverInputDStream<String> lines = jsc.socketTextStream("CentOS16", 9999);
JavaDStream<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
private static final long serialVersionUID = 1L;
@Override
public Iterable<String> call(String s) {
return Arrays.asList(s.split(" "));
}
});
JavaPairDStream<String, Integer> ones = words.mapToPair(new PairFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<String, Integer> call(String s) {
return new Tuple2<String, Integer>(s, 1);
}
});
JavaPairDStream<String, Integer> counts =
ones.updateStateByKey(new Function2<List<Integer>, Optional<Integer>, Optional<Integer>>() {
private static final long serialVersionUID = 1L;
@Override
public Optional<Integer> call(List<Integer> values, Optional<Integer> state) throws Exception {
/**
* values:经过分组最后 这个key所对应的value [1,1,1,1,1]
* state:这个key在本次之前之前的状态
*/
Integer updateValue = 0 ;
if(state.isPresent()){
updateValue = state.get();
}
for (Integer value : values) {
updateValue += value;
}
return Optional.of(updateValue);
}
});
//output operator
counts.print();
jsc.start();
jsc.awaitTermination();
jsc.close();
}
count算子:
count: 通过计算源DStream的每个RDD中的元素数量,返回单元素RDD的新DStream。
public class Operate_count {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("Operate_count");
JavaStreamingContext jsc = new JavaStreamingContext(conf,Durations.seconds(5));
JavaDStream<String> textFileStream = jsc.textFileStream("data");
JavaDStream<Long> count = textFileStream.count();
count.print();
jsc.start();
jsc.awaitTermination();
jsc.close();
}
}
countByValue:
当调用类型为K的元素的DStream时,返回(K,Long)键值对的新DStream,
其中键值对的value是key对应的value在Dstream中出现的次数.
public class Operate_countByValue {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("Operate_countByValue");
JavaStreamingContext jsc = new JavaStreamingContext(conf,Durations.seconds(5));
JavaDStream<String> textFileStream = jsc.textFileStream("data");
JavaPairDStream<String, Integer> mapToPair = textFileStream.mapToPair(new PairFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L;
public Tuple2<String, Integer> call(String s) throws Exception {
return new Tuple2<String, Integer>(s.split(" ")[0].trim(),Integer.valueOf(s.split(" ")[1].trim()));
}
});
JavaPairDStream<Tuple2<String, Integer>, Long> countByValue = mapToPair.countByValue();
countByValue.print(1000);
jsc.start();
jsc.awaitTermination();
jsc.close();
}
}
join:数据上面的合并,会把多个Dstream的数据进行合并
当(K,V)格式和(K,W)格式的两个Dstream使用时,返回一个新的(K,(V,W))格式的DStream。
注意:join 作用在(K,V)格式的DStream
public class Operate_join {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("Operate_join");
JavaStreamingContext jsc = new JavaStreamingContext(conf,Durations.seconds(5));
JavaDStream<String> textFileStream = jsc.textFileStream("data");
//flatMapToPair算子,读取一行数据,以空格切分,出去一堆RDD数据
JavaPairDStream<String, Integer> flatMapToPair = textFileStream.flatMapToPair(new PairFlatMapFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
public Iterable<Tuple2<String, Integer>> call(String t)
throws Exception {
return Arrays.asList(new Tuple2<String , Integer>(t.trim(), 1));
}
});
flatMapToPair.join(flatMapToPair).print(1000);
jsc.start();
jsc.awaitTermination();
jsc.close();
}
}
union:逻辑上面的合并,不会对数据进行处理
返回一个新的DStream,它包含源DStream和otherDStream中元素的并集。
public class Operate_union {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("Operate_union");
JavaStreamingContext jsc = new JavaStreamingContext(conf,
Durations.seconds(5));
JavaDStream<String> textFileStream1 = jsc.textFileStream("data");
JavaDStream<String> textFileStream2 = jsc.textFileStream("data");
JavaDStream<String> union = textFileStream1.union(textFileStream2);
union.print(1000);
jsc.start();
jsc.awaitTermination();
jsc.close();
}
}
reduce算子
/**
*reduce(func): 通过使用函数func(其接受两个参数并返回一个)聚合DStream的每个RDD中的元素,
*返回单元素RDD的新DStream 。该函数是关联的,以便可以并行计算。
*reduce 处理后返回的是一条数据结果
*
*/
public class Operate_reduce {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("Operate_reduce");
JavaStreamingContext jsc = new JavaStreamingContext(conf,Durations.seconds(5));
JavaDStream<String> textFileStream = jsc.textFileStream("data");
/**
* 下面是拼接本次和下次的字符串来模拟reduce处理数据
*/
JavaDStream<String> reduce = textFileStream.reduce(new Function2<String, String, String>() {
private static final long serialVersionUID = 1L;
public String call(String s1, String s2) throws Exception {
return s1+"****"+s2;
}
});
reduce.print();
jsc.start();
jsc.awaitTermination();
jsc.close();
}
}