1 sourceStream必須要先keyBy然後才能使用Keyed State
2 需要繼承RichxxxxFunction纔行,在open之前聲明,在open中初始化,在算子方法中使用和處理。不能繼承xxxxxFunction,因爲沒有open方法,無法初始化,會報錯。
3 open方法中只能初始化Keyed State,無法使用Keyed State(比如:獲取值等操作),不然報錯。因爲open方法不屬於Keyed上下文,算子方法才屬於Keyed上下文
並行度是1:2個不同key流被1個子任務處理
package StateTtlConfig;
/**
* @Author you guess
* @Date 2020/6/22 22:42
* @Version 1.0
* @Desc
*/
import org.apache.flink.api.common.functions.RichFlatMapFunction;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.util.Collector;
import java.io.IOException;
public class StateTest1 {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<Tuple2<String, Long>> source1 = env.addSource(new SourceFunction<Tuple2<String, Long>>() {
@Override
public void run(SourceContext<Tuple2<String, Long>> ctx) throws Exception {
while (true) {
Thread.sleep(100);
ctx.collect(Tuple2.of("a", 1L));
Thread.sleep(100);
ctx.collect(Tuple2.of("b", 2L));
Thread.sleep(100);
ctx.collect(Tuple2.of("a", 3L));
Thread.sleep(100);
ctx.collect(Tuple2.of("b", 4L));
Thread.sleep(100);
ctx.collect(Tuple2.of("a", 5L));
Thread.sleep(100);
ctx.collect(Tuple2.of("b", 6L));
Thread.sleep(100);
ctx.collect(Tuple2.of("a", 7L));
Thread.sleep(100);
ctx.collect(Tuple2.of("b", 8L));
break;
}
}
@Override
public void cancel() {
}
});//source1
//KeyedState必須要用在keyBy後面!!不然報錯!!
//Keyed state can only be used on a 'keyed stream', i.e., after a 'keyBy()' operation.
source1.keyBy(0)
.flatMap(new CountWindowAverage()).setParallelism(1)
.print();
env.execute("Flink StateTTL Test1");
}
/**
* KeyedState
*/
public static class CountWindowAverage extends RichFlatMapFunction<Tuple2<String, Long>, Tuple2<String, Long>> {
/**
* The ValueState handle. The first field is the count, the second field a running sum.
* 聲明
*/
ValueState<Tuple2<Long, Long>> averageKeyedState;
@Override
public void open(Configuration config) throws IOException {
ValueStateDescriptor<Tuple2<Long, Long>> descriptor = new ValueStateDescriptor<Tuple2<Long, Long>>(
"average", // the state name
TypeInformation.of(new TypeHint<Tuple2<Long, Long>>() {
}), // type information
Tuple2.of(0L, 0L)); // default value of the state, if nothing was set
//初始化
averageKeyedState = getRuntimeContext().getState(descriptor);
//System.out.println("open...averageKeyedState:"+averageKeyedState.value());
//NullPointerException: No key set. This method should not be called outside of a keyed context.
}//open
@Override
public void flatMap(Tuple2<String, Long> input, Collector<Tuple2<String, Long>> out) throws Exception {
// access the state value
Tuple2<Long, Long> currentSum = averageKeyedState.value();
// update the count
currentSum.f0 += 1;
// add the second field of the input value
currentSum.f1 += input.f1;
// update the state
// 使用
averageKeyedState.update(currentSum);
System.out.println("sumKeyedState:" + averageKeyedState.value()+",線程id#"+Thread.currentThread().getId());
// if the count reaches 2, emit the average and clear the state
if (currentSum.f0 >= 2) {
out.collect(new Tuple2<>(input.f0, currentSum.f1 / currentSum.f0));
averageKeyedState.clear();
}
}//flatMap
}//CountWindowAverage
}
/*
輸出:
sumKeyedState:(1,1),線程id#72
sumKeyedState:(1,2),線程id#72
sumKeyedState:(2,4),線程id#72
sumKeyedState:(2,6),線程id#72
8> (a,2)
9> (b,3)
sumKeyedState:(1,5),線程id#72
sumKeyedState:(1,6),線程id#72
sumKeyedState:(2,12),線程id#72
10> (a,6)
sumKeyedState:(2,14),線程id#72
11> (b,7)
* */
並行度是不設置(默認是12):
//KeyedState必須要用在keyBy後面!!不然報錯!!
//Keyed state can only be used on a 'keyed stream', i.e., after a 'keyBy()' operation.
source1.keyBy(0)
.flatMap(new CountWindowAverage())//.setParallelism(1)
.print();
/*
輸出:
sumKeyedState:(1,1),線程id#81
sumKeyedState:(1,2),線程id#74
sumKeyedState:(2,4),線程id#81
8> (a,2)
sumKeyedState:(2,6),線程id#74
3> (b,3)
sumKeyedState:(1,5),線程id#81
sumKeyedState:(1,6),線程id#74
sumKeyedState:(2,12),線程id#81
8> (a,6)
sumKeyedState:(2,14),線程id#74
3> (b,7)
*/
flink1.9.2,java1.8