Flink aggregate 方法解析

在Flink计算中,常见的一些操作是map或者flatmap一些数据之后keyby 开窗口进行计算。那么在这些计算当中有哪些算子呢?

其中我分为两类算子。

增量聚合reduceaggregate算子,全量聚合applyprocess。那么今天我们就主要讲解一下常用的增量聚合算子aggregate算子。
aggregate方法签名的三个类型 <数据源类型,累加器类型,输出类型>
WindowFunction 方法签名的四个类型为 <IN, OUT, KEY, W extends Window>
aggregate算子,有几个重载方法:

image-20210301221245136

这里我们选用 第三个,因为我经常用这个,因为我需要获取key,剩下的看代码把。
拿aggregate方法我们可以计算很多指标,在一个累加器中,例如SUM、MIN、MAX等

package com.bigdata.agg;

import com.google.common.util.concurrent.AtomicDouble;
import lombok.Data;
import org.apache.flink.api.common.functions.AggregateFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.functions.windowing.WindowFunction;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.util.Collector;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Copyright (c) 2019 bigdata ALL Rights Reserved
 * Project: learning
 * Package: com.bigdata.agg
 * Version: 1.0
 *
 * @author qingzhi.wu 2021/3/1 21:53
 */
public class Main {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env =  StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        ArrayList<String> datas = new ArrayList<>();
        datas.add("1000,网上商城,200.0");
        datas.add("1500,线下门店,100.0");
        datas.add("1300,美团配送,200.0");
        datas.add("1600,网上商城,100.0");
        DataStreamSource<String> dataStreamSource = env.fromCollection(datas);
        SingleOutputStreamOperator<String> source = dataStreamSource.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<String>(Time.of(1, TimeUnit.SECONDS)) {
            @Override
            public long extractTimestamp(String s) {
                return Long.parseLong(s.split(",")[0]);
            }
        });
        SingleOutputStreamOperator<TestData> testDataStream = source.map(new MapFunction<String, TestData>() {
            @Override
            public TestData map(String line) throws Exception {
                long timestamp = Long.parseLong(line.split(",")[0]);
                String channel = line.split(",")[1];
                double amt = Double.parseDouble(line.split(",")[2]);
                return new TestData(timestamp, channel, amt);
            }
        });
        testDataStream.keyBy(new KeySelector<TestData, String>() {
            @Override
            public String getKey(TestData testData) throws Exception {
                return testData.channel;
            }
        }).window(TumblingEventTimeWindows.of(Time.of(1, TimeUnit.SECONDS)))
                .aggregate(new AggregateFunction<TestData, Acc, String>() {
                    @Override
                    public Acc createAccumulator() {
                        Acc acc = new Acc();
                        acc.init();
                        return acc;
                    }

                    @Override
                    public Acc add(TestData testData, Acc acc) {
                        acc.count.getAndAdd(1);
                        acc.sum.getAndAdd(testData.amt);
                        return acc;
                    }

                    @Override
                    public String getResult(Acc acc) {
                        return acc.toString();
                    }

                    @Override
                    public Acc merge(Acc acc, Acc acc1) {
                        acc.count.addAndGet(acc1.count.get());
                        acc.sum.addAndGet(acc1.count.get());

                        return acc;
                    }
                }, new WindowFunction<String, String, String, TimeWindow>() {
                    @Override
                    public void apply(String key, TimeWindow timeWindow, Iterable<String> iterable, Collector<String> out) throws Exception {
                        Iterator<String> iterator = iterable.iterator();
                        while (iterator.hasNext()) {
                            String value = iterator.next();
                            out.collect(key + "," + value );
                        }
                    }
                }).print();


        env.execute("Aggregate test");
    }
    @Data
    private static class Acc {
        AtomicDouble sum;
        AtomicLong count;

        public void init() {
            sum = new AtomicDouble(0);
            count = new AtomicLong(0);
        }

        public Acc() {
        }

        @Override
        public String toString() {
            return sum +"," + count;
        }
    }

    @Data
    private static class TestData {
        long timestamp;
        String channel;
        Double amt;

        public TestData() {
        }

        public TestData(long timestamp, String channel, Double amt) {
            this.timestamp = timestamp;
            this.channel = channel;
            this.amt = amt;
        }
    }
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Apache Flink 中,DataStream API 中的 aggregate 方法用于对流数据进行聚合操作。该方法的参数说明如下: ``` public <T, A, R> SingleOutputStreamOperator<R> aggregate(AggregateFunction<T, A, R> function, WindowAssigner<? super T, W> windowAssigner, Trigger<? super T, ? super W> trigger, Evictor<? super T, ? super W> evictor, AllowedLateness allowedLateness, OutputTag lateDataOutputTag) ``` 其中各参数的含义如下: - function:AggregateFunction 类型,表示聚合函数,用于定义聚合逻辑。 - windowAssigner:WindowAssigner 类型,表示窗口分配器,用于定义数据元素如何分配到不同的窗口中。 - trigger:Trigger 类型,表示触发器,用于定义窗口如何触发计算。 - evictor:Evictor 类型,表示清除器,用于定义窗口中哪些元素应该被清除。 - allowedLateness:AllowedLateness 类型,表示允许延迟的时间,用于定义窗口计算的最大允许延迟时间。 - lateDataOutputTag:OutputTag 类型,表示迟到的数据标记,用于标记迟到的数据。 其中前四个参数为必选参数,后两个参数为可选参数。 聚合函数 AggregateFunction 是必选参数,该函数用于定义聚合逻辑,需要实现 AggregateFunction 接口,并重写该接口中的四个方法:createAccumulator()、add()、getResult() 和 merge()。 窗口分配器 WindowAssigner、触发器 Trigger 和清除器 Evictor 也是必选参数,用于定义窗口如何分配、触发和清除。Flink 提供了多种窗口分配器、触发器和清除器的实现,也可以根据需求自定义实现。 允许延迟的时间 AllowedLateness 和迟到的数据标记 OutputTag 均为可选参数,用于定义窗口计算的最大允许延迟时间和标记迟到的数据。如果不指定这两个参数,则 Flink 默认不允许延迟,迟到的数据会被丢弃。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值