Flink Keyed State 實例

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章