Flink 之 KeyedState 的使用

場景:
        不使用 Flink 提供的 sum() 方法,使用 KeyedState 完成對單詞分組求和計算操作。

代碼:
/**
 * TODO 不使用 Flink 提供的sum()方法,對單詞進行分組求和計算。
 *
 * @author liuzebiao
 * @Date 2020-2-17 11:42
 */
public class KeyedStateDemo {

    public static void main(String[] args) throws Exception {
        //1.創建一個 flink steam 程序的執行環境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        //2.使用StreamExecutionEnvironment創建DataStream
        DataStreamSource<String> lines = env.socketTextStream( "localhost", 8888);

        //Transformation(s) 對數據進行處理操作
        SingleOutputStreamOperator<Tuple2<String, Integer>> wordAndOne = lines.map(new MapFunction<String, Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> map(String word) {
                //將每個單詞與 1 組合,形成一個元組
                return Tuple2.of(word, 1);
            }
        });

        //進行分組聚合(keyBy:將key相同的分到一個組中)
        KeyedStream<Tuple2<String, Integer>, Tuple> keyedStream = wordAndOne.keyBy(0);

        /** 使用 KeyedState 通過中間狀態求和  ----- start ----**/
        SingleOutputStreamOperator<Tuple2<String, Integer>> summed = keyedStream.map(new RichMapFunction<Tuple2<String, Integer>, Tuple2<String, Integer>>() {

            //狀態數據不參與序列化,添加 transient 修飾
            private transient ValueState<Integer> valueState;

            @Override
            public void open(Configuration parameters) throws Exception {
                //獲取 KeyedState 數據
                ValueStateDescriptor stateDescriptor = new ValueStateDescriptor("sum-key-state", Types.TUPLE(Types.STRING, Types.INT));

                valueState = getRuntimeContext().getState(stateDescriptor);
            }

            @Override
            public Tuple2<String, Integer> map(Tuple2<String, Integer> tuple2) throws Exception {
                //輸入的單詞
                String word = tuple2.f0;
                //輸入的次數
                Integer count = tuple2.f1;
                //根據State獲取中間數據
                Integer historyVal = valueState.value();

                //根據State中間數據,進行累加
                if (historyVal != null) {
                    historyVal += count;
                    //累加後,更新State數據
                    valueState.update(historyVal);
                } else {
                    valueState.update(count);
                }
                return Tuple2.of(word,valueState.value());
            }
        });

        /** 使用 KeyedState 通過中間狀態求和  ----- end ----**/

        //Transformation 結束

        //3.調用Sink (Sink必須調用)
        summed.print();

        //啓動(這個異常不建議try...catch... 捕獲,因爲它會拋給上層flink,flink根據異常來做相應的重啓策略等處理)
        env.execute("KeyedStateDemo");
    }
}
 

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