7、Flink 自定义 WaterMarkGenerator 案例

1、MyWaterMarkWatermarkGeneratorPeriodic

该 watermark 生成器场景:数据源在一定程度上乱序,即某个最新到达的时间戳为 t 的元素将在最早到达的时间戳为 t 的元素之后最多 n 毫秒到达。

bash 复制代码
class MyBoundedOutOfOrdernessGenerator implements WatermarkGenerator<_01_MyEvent> {
    // 3 秒
    private final long maxOutOfOrderness = 3000;

    private long currentMaxTimestamp;

    // 每到达一条数据执行一次,获取当前的最大时间戳
    @Override
    public void onEvent(_01_MyEvent event, long eventTimestamp, WatermarkOutput output) {
        currentMaxTimestamp = Math.max(currentMaxTimestamp, eventTimestamp);
        System.out.println("当前的数据ID为=>" + event.getId() + ",currentMaxTimestamp=>" + currentMaxTimestamp);
    }

    // 每到达一个周期触发一次,下发 Watermark
    @Override
    public void onPeriodicEmit(WatermarkOutput output) {
        // 发出的 watermark = 当前最大时间戳 - 最大乱序时间
        Watermark watermark = new Watermark(currentMaxTimestamp - maxOutOfOrderness - 1);
        output.emitWatermark(watermark);
        System.out.println("下发的 Watermark 为=>" + watermark.getTimestamp());
    }
}

数据输入与输出案例

bash 复制代码
  输入输出demo数据演示如下
 
  下发的 Watermark 为=>-3001
 
  1,a,1714028400000
 
  res=>(1,a,1714028400000,-3001)
  (1,a,1714028400000,-3001)
  当前的数据ID为=>1,currentMaxTimestamp=>1714028400000
  下发的 Watermark 为=>1714028396999
 
  1,b,1714028410000
 
  res=>(1,b,1714028410000,1714028396999)
  (1,b,1714028410000,1714028396999)
  当前的数据ID为=>1,currentMaxTimestamp=>1714028410000
  下发的 Watermark 为=>1714028406999
 
  1,c,1714028410001
 
  res=>(1,c,1714028410001,1714028406999)
  (1,c,1714028410001,1714028406999)
  当前的数据ID为=>1,currentMaxTimestamp=>1714028410001
  下发的 Watermark 为=>1714028407000

2、MyTimeLagWatermarkGenerator

该生成器生成的 watermark 滞后于处理时间固定量,它假定元素会在有限延迟后到达 Flink。

bash 复制代码
class MyTimeLagWatermarkGenerator implements WatermarkGenerator<_01_MyEvent> {
    // 3 秒
    private final long maxTimeLag = 3000;

    @Override
    public void onEvent(_01_MyEvent event, long eventTimestamp, WatermarkOutput output) {
        // 处理时间场景下,不需要实现 onEvent
        System.out.println("处理时间场景下,不需要实现 onEvent");
    }

    @Override
    public void onPeriodicEmit(WatermarkOutput output) {
        Watermark watermark = new Watermark(System.currentTimeMillis() - maxTimeLag);
        output.emitWatermark(watermark);
        System.out.println("下发的 Watermark 为=>" + watermark.getTimestamp());
    }
}

数据输入与输出案例

bash 复制代码
  下发的 Watermark 为=>1714284213511
 
  1,a,1714028400000
 
  res=>(1,a,1714028400000,1714284230336)
  (1,a,1714028400000,1714284230336)
  处理时间场景下,不需要实现 onEvent
  下发的 Watermark 为=>1714284230540
 
  1,b,1714028410000
 
  res=>(1,b,1714028410000,1714284254960)
  (1,b,1714028410000,1714284254960)
  处理时间场景下,不需要实现 onEvent
  下发的 Watermark 为=>1714284255166
 
  1,c,1714028410001
 
  res=>(1,c,1714028410001,1714284266639)
  (1,c,1714028410001,1714284266639)
  处理时间场景下,不需要实现 onEvent
  下发的 Watermark 为=>1714284266846

3、完整测试用例

bash 复制代码
import org.apache.flink.api.common.eventtime.*;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.tuple.Tuple4;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.ProcessFunction;
import org.apache.flink.util.Collector;

public class _01_MyWaterMarkWatermarkGeneratorPeriodic {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        // 设置水位线生成的时间间隔
        env.getConfig().setAutoWatermarkInterval(2000L);

        DataStreamSource<String> source = env.socketTextStream("localhost", 8888);
        source.map(new MapFunction<String, _01_MyEvent>() {
                    @Override
                    public _01_MyEvent map(String value) throws Exception {
                        String[] fields = value.split(",");
                        return new _01_MyEvent(Integer.parseInt(fields[0])
                                , fields[1]
                                , Long.parseLong(fields[2]));
                    }
                    // 分配水位线策略
                }).assignTimestampsAndWatermarks(new WatermarkStrategy<_01_MyEvent>() {
                    @Override
                    public WatermarkGenerator<_01_MyEvent> createWatermarkGenerator(WatermarkGeneratorSupplier.Context context) {
//                        return new MyBoundedOutOfOrdernessGenerator();
                        return new MyTimeLagWatermarkGenerator();
                    }
                    // 分配时间戳字段
                }.withTimestampAssigner(new SerializableTimestampAssigner<_01_MyEvent>() {
                    @Override
                    public long extractTimestamp(_01_MyEvent element, long recordTimestamp) {
                        return element.getEventTime();
                    }
                }))
                .process(new ProcessFunction<_01_MyEvent, Tuple4<Integer,String,Long,Long>>() {
                    @Override
                    public void processElement(_01_MyEvent value, ProcessFunction<_01_MyEvent, Tuple4<Integer, String, Long, Long>>.Context ctx, Collector<Tuple4<Integer, String, Long, Long>> out) throws Exception {
                        Tuple4<Integer, String, Long, Long> res = new Tuple4<>(value.getId(), value.getName(), value.getEventTime(), ctx.timerService().currentWatermark());
                        System.out.println("res=>"+res);
                        out.collect(res);
                    }
                })
                .print();

        env.execute();
    }
}

用到的 pojo 类

bash 复制代码
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class _01_MyEvent implements Serializable {
    private Integer id;
    private String name;
    private Long eventTime;
}
相关推荐
2401_883041081 小时前
新锐品牌电商代运营公司都有哪些?
大数据·人工智能
青云交1 小时前
大数据新视界 -- 大数据大厂之 Impala 性能优化:融合机器学习的未来之路(上 (2-1))(11/30)
大数据·计算资源·应用案例·数据交互·impala 性能优化·机器学习融合·行业拓展
Json_181790144804 小时前
An In-depth Look into the 1688 Product Details Data API Interface
大数据·json
Qspace丨轻空间6 小时前
气膜场馆:推动体育文化旅游创新发展的关键力量—轻空间
大数据·人工智能·安全·生活·娱乐
Elastic 中国社区官方博客7 小时前
如何将数据从 AWS S3 导入到 Elastic Cloud - 第 3 部分:Elastic S3 连接器
大数据·elasticsearch·搜索引擎·云计算·全文检索·可用性测试·aws
Aloudata8 小时前
从Apache Atlas到Aloudata BIG,数据血缘解析有何改变?
大数据·apache·数据血缘·主动元数据·数据链路
水豚AI课代表8 小时前
分析报告、调研报告、工作方案等的提示词
大数据·人工智能·学习·chatgpt·aigc
拓端研究室TRL11 小时前
【梯度提升专题】XGBoost、Adaboost、CatBoost预测合集:抗乳腺癌药物优化、信贷风控、比特币应用|附数据代码...
大数据
黄焖鸡能干四碗11 小时前
信息化运维方案,实施方案,开发方案,信息中心安全运维资料(软件资料word)
大数据·人工智能·软件需求·设计规范·规格说明书
编码小袁11 小时前
探索数据科学与大数据技术专业本科生的广阔就业前景
大数据