Flink1.10实战:自定义聚合函数AggregateFunction

微信公众号:大数据开发运维架构

关注可了解更多大数据相关的资讯。问题或建议,请公众号留言;

如果您觉得“大数据开发运维架构”对你有帮助,欢迎转发朋友圈

从微信公众号拷贝过来,格式有些错乱,建议直接去公众号阅读


一,概述
    Flink 的AggregateFunction是一个基于中间计算结果状态进行增量计算的函数。由于是迭代计算方式,所以,在窗口处理过程中,不用缓存整个窗口的数据,所以效率执行比较高。

二,AggregateFunction接口类

    AggregateFunction比ReduceFunction更加通用,它有三个参数:输入类型(IN),累加器类型(ACC)和输出类型(OUT)


@PublicEvolving
public interface AggregateFunction<IN, ACC, OUT> extends Function, Serializable {
  ...............................
}

自定义聚合函数需要实现AggregateFunction接口类,它有四个接口实现方法:

a.创建一个新的累加器,启动一个新的聚合,负责迭代状态的初始化

ACC createAccumulator();

b.对于数据的每条数据,和迭代数据的聚合的具体实现

ACC add(IN value, ACC accumulator);

c.合并两个累加器,返回一个具有合并状态的累加器

ACC merge(ACC a, ACC b);

d.从累加器获取聚合的结果

OUT getResult(ACC accumulator);

三、代码实例   

1.模拟场景:

    从文件/socket读取数据,数据包含三个字段:商品ID,用户ID,访问类型(1.点击查看 2.收藏 3.购买),访问时间;这里每隔3秒对最近6秒内的数据进行汇总计算各个商品的“点击查看”访问量,也就是访问类型为1的数据。

    
    这里自定义聚合函数MyCountAggregate数据进行预聚合,自定义窗口函数MyCountWindowFunction2对聚合的数据封装成字符串,并加上窗口结束时间信息进行输出。

2.数据准备:


product1,user14,1,1586855115084
product2,user19,2,1586855116087
product2,user19,1,1586855116087
product3,user17,1,1586855117089
product1,user17,1,1586855118092
product2,user17,1,1586855119095
product3,user15,1,1586855120097
product1,user12,1,1586855121100
product2,user13,1,1586855122102
product3,user13,1,1586855123105
product1,user13,1,1586855124108
product2,user19,3,1586855116087
product2,user16,1,1586855125111
product1,user17,1,1586855136113
product1,user14,1,1586855127116
product2,user16,1,1586855128119
product2,user16,1,1586855129122
product3,user16,1,1586855130125
product2,user11,1,1586855131128
product1,user16,1,1586855132131
product2,user13,1,1586855133134
product3,user16,1,1586855134137
product3,user13,1,1586855135139
product2,user19,3,1586855116087
product1,user18,1,1586855136142
product2,user12,1,1586855137145
product1,user13,1,1586855138148
product3,user17,1,1586855139150

3.自定义聚合函数MyCountAggregate


package com.hadoop.ljs.flink110.aggreagate;
import org.apache.flink.api.common.functions.AggregateFunction;
/**
 * @author: Created By lujisen
 * @company ChinaUnicom Software JiNan
 * @date: 2020-04-15 22:00
 * @version: v1.0
 * @description: com.hadoop.ljs.flink110.aggreagate
 * 输入类型(IN)、累加器类型(ACC)和输出类型(OUT)。
 */
public class MyCountAggregate implements AggregateFunction<ProductViewData, Long, Long> {
    @Override
    public Long createAccumulator() {
        /*访问量初始化为0*/
        return 0L;
    }
    @Override
    public Long add(ProductViewData value, Long accumulator) {
        /*访问量直接+1 即可*/
        return accumulator+1;
    }
    @Override
    public Long getResult(Long accumulator) {
        return accumulator;
    }
    /*合并两个统计量*/
    @Override
    public Long merge(Long a, Long b) {
        return a+b;
    }
}

4.自定义窗口函数

package com.hadoop.ljs.flink110.aggreagate;
import org.apache.flink.streaming.api.functions.windowing.WindowFunction;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.util.Collector;
/**
 * @author: Created By lujisen
 * @company ChinaUnicom Software JiNan
 * @date: 2020-04-15 21:56
 * @version: v1.0
 * @description: com.hadoop.ljs.flink110.aggreagate
 *  *自定义窗口函数,封装成字符串
 *  *第一个参数是上面MyCountAggregate的输出,就是商品的访问量统计
 *  * 第二个参数 输出 这里为了演示 简单输出字符串
 *  * 第三个就是 窗口类 能获取窗口结束时间
 */
public class MyCountWindowFunction2 implements WindowFunction<Long,String,String, TimeWindow> {
@Override
public void apply(String productId, TimeWindow window, Iterable<Long> input, Collector<String> out) throws Exception {
     /*商品访问统计输出*/
    /*out.collect("productId"productId,window.getEnd(),input.iterator().next()));*/
    out.collect("----------------窗口时间:"+window.getEnd());
    out.collect("商品ID: "+productId+"  浏览量: "+input.iterator().next());
    }
}

5.主函数,代码如下:


package com.hadoop.ljs.flink110.aggreagate;

import org.apache.flink.api.common.functions.FilterFunction;
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.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.timestamps.AscendingTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;

/**
 * @author: Created By lujisen
 * @company ChinaUnicom Software JiNan
 * @date: 2020-04-14 11:28
 * @version: v1.0
 * @description: com.hadoop.ljs.flink110.aggreagate
 * 自定义聚合函数类和窗口类,进行商品访问量的统计,根据滑动时间窗口,按照访问量排序输出
 */
public class AggregateFunctionMain2 {

    public  static int windowSize=6000;/*滑动窗口大小*/
    public  static int windowSlider=3000;/*滑动窗口滑动间隔*/
    
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment senv = StreamExecutionEnvironment.getExecutionEnvironment();
        senv.setParallelism(1);
        senv.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        /*DataStream<String> sourceData = senv.socketTextStream("localhost",9000);*/ 
        //从文件读取数据,也可以从socket读取数据       
        DataStream<String> sourceData = senv.readTextFile("D:\\projectData\\ProductViewData2.txt");
        DataStream<ProductViewData> productViewData = sourceData.map(new MapFunction<String, ProductViewData>() {
            @Override
            public ProductViewData map(String value) throws Exception {
                String[] record = value.split(",");
                return new ProductViewData(record[0], record[1], Long.valueOf(record[2]), Long.valueOf(record[3]));
            }
        }).assignTimestampsAndWatermarks(new AscendingTimestampExtractor<ProductViewData>(){
            @Override
            public long extractAscendingTimestamp(ProductViewData element) {
                return element.timestamp;
            }
        });
        /*过滤操作类型为1  点击查看的操作*/
        DataStream<String> productViewCount = productViewData.filter(new FilterFunction<ProductViewData>() {
            @Override
            public boolean filter(ProductViewData value) throws Exception {
                if(value.operationType==1){
                    return true;
                }
                return false;
            }
        }).keyBy(new KeySelector<ProductViewData, String>() {
            @Override
            public String getKey(ProductViewData value) throws Exception {
                return value.productId;
            }
            //时间窗口 6秒  滑动间隔3秒
        }).timeWindow(Time.milliseconds(windowSize), Time.milliseconds(windowSlider))
        /*这里按照窗口进行聚合*/
        .aggregate(new MyCountAggregate(), new MyCountWindowFunction2());
        //聚合结果输出
        productViewCount.print();

        senv.execute("AggregateFunctionMain2");
    }
}

   这里自定义聚合函数演示完毕,感谢关注!!!

   如果觉得我的文章能帮到您,请关注微信公众号“大数据开发运维架构”,并转发朋友圈,谢谢支持!

 

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陆继森

您的鼓励将是我们创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值