1.说明
SparkStreaming的一般是7天24小时不停息的运行,而在运行的时候,中间会有很多的状态,而有些状态我们需要一些操作,比如累计,更新或者其他的操作。那么如何将这些独立的状态联系起来就成了一种迫切的需求。
2.介绍
UpdateStateByKey的主要功能:
1、为Spark Streaming中每一个Key维护一份state状态,state类型可以是任意类型的, 可以是一个自定义的对象,那么更新函数也可以是自定义的。
2、通过更新函数对该key的状态不断更新,对于每个新的batch而言,Spark Streaming会在使用updateStateByKey的时候为已经存在的key进行state的状态更新。
注意
使用到updateStateByKey要开启checkpoint机制和功能。
多久会将内存中的数据写入到磁盘一份?
如果batchInterval设置的时间小于10秒,那么10秒写入磁盘一份。如果batchInterval设置的时间大于10秒,那么就会batchInterval时间间隔写入磁盘一份
代码示例,先在158.158.4.49上,开启nc发送消息
package cn.taobao;
import org.apache.spark.api.java.Optional;
import org.apache.spark.api.java.StorageLevels;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.streaming.Durations;
import org.apache.spark.streaming.api.java.JavaDStream;
import org.apache.spark.streaming.api.java.JavaPairDStream;
import org.apache.spark.streaming.api.java.JavaReceiverInputDStream;
import org.apache.spark.streaming.api.java.JavaStreamingContext;
import scala.Tuple2;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
public class Other_state {
public static void main(String[] args) throws Exception {
// StreamingContext 编程入口
JavaStreamingContext ssc = new JavaStreamingContext(
"local[*]",
"JavaLocalNetworkWordCount",
Durations.seconds(1),
System.getenv("SPARK_HOME"),
JavaStreamingContext.jarOfClass(Other_state.class.getClass()));
ssc.sparkContext().setLogLevel("ERROR");
//这里测试用,正式环境要用hdfs目录
ssc.sparkContext().setCheckpointDir("C:\\Users\\need\\Desktop\\ha");
//数据接收器(Receiver)
//创建一个接收器(JavaReceiverInputDStream),这个接收器接收一台机器上的某个端口通过socket发送过来的数据并处理
JavaReceiverInputDStream<String> lines = ssc.socketTextStream(
"158.158.4.49", 9998, StorageLevels.MEMORY_AND_DISK_SER);
JavaDStream<String> words = lines.flatMap(x -> Arrays.asList(Pattern.compile(" ").split(x)).iterator());
JavaPairDStream<String, Integer> wordsDstream = words.mapToPair(s -> new Tuple2<>(s, 1));
Function2<List<Integer>, Optional<Integer>, Optional<Integer>> updateFunction =
/*
List<Integer> values 应该就是每个单词的计数列表
Optional<Integer> state 每个单词的个数统计
假如输入 aa bb cc aa
那么 values为以下
[1, 1]
[1]
[1]
state 为以下
Optional[2]
Optional[1]
Optional[1]
-------------------------------------------
Time: 1619607044000 ms
-------------------------------------------
(aa,2)
(bb,1)
(cc,1)
假如又输入bb bb cc
那么 values为以下
[]
[1, 1]
[1]
state为以下
Optional[2]
Optional[3]
Optional[2]
-------------------------------------------
Time: 1619607331000 ms
-------------------------------------------
(aa,2)
(bb,3)
(cc,2)
*/
(values, state) -> {
System.out.println(values);
System.out.println(state);
//初始化一个变量
int out = 0;
//先判断是不是为null
if (state.isPresent()) {
//该变量用于更新,加上上一个状态的值,如果有上一个状态就获取,如果没有就赋值为0
out = out + state.get();
}
//遍历当前的序列,序列里面每一个元素都是当前批次的数据计算结果,累加上一次的计算结果
for (Integer v : values) {
out = out + v;
}
//返回一个Optional对象
return Optional.of(out);
};
JavaPairDStream<String, Integer> runningCounts = wordsDstream.updateStateByKey(updateFunction);
runningCounts.print();
//显式的启动数据接收
ssc.start();
try {
//来等待计算完成
ssc.awaitTermination();
} catch (Exception e) {
e.printStackTrace();
} finally {
ssc.close();
}
}
}