Flink原理:定时器

1. 用途

Flink定时器存在于窗口的触发,TTL等诸多用途,因此搞清楚其原理对于理解这些知识点至关重要。

2. 示例

在flink实时处理中,涉及到延时处理可使用KeyedProcessFunction来完成,KeyedProcessFunction是flink提供面向用户的low level api,可以访问状态、当前的watermark或者当前的processingtime, 更重要的是提供了注册定时器的功能,分为:

  1. 注册处理时间定时器,直到系统的processingTime超过了注册的时间就会触发定时任务
  2. 注册事件时间定时器,直到watermark值超过了注册的时间就会触发定时任务另外也可以删除已经注册的定时器。

示例代码如下:

// 创建bean类CountWithTimestamp,里面有三个字段
package com.bolingcavalry.keyedprocessfunction;

public class CountWithTimestamp {
   
    public String key;
    public long count;
    public long lastModified;
}
// 创建FlatMapFunction的实现类Splitter,作用是将字符串分割后生成多个Tuple2实例,f0是分隔后的单词,f1等于1:
package com.bolingcavalry;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.util.Collector;
import org.apache.flink.util.StringUtils;

public class Splitter implements FlatMapFunction<String, Tuple2<String, Integer>> {
   
    @Override
    public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
   

        if(StringUtils.isNullOrWhitespaceOnly(s)) {
   
            System.out.println("invalid line");
            return;
        }

        for(String word : s.split(" ")) {
   
            collector.collect(new Tuple2<String, Integer>(word, 1));
        }
    }
}
// 最后是整个逻辑功能的主体:ProcessTime.java,这里面有自定义的KeyedProcessFunction子类,还有程序入口的main方法
package com.bolingcavalry.keyedprocessfunction;

import com.bolingcavalry.Splitter;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.java.tuple.Tuple;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
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.AssignerWithPeriodicWatermarks;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.streaming.api.watermark.Watermark;
import org.apache.flink.util.Collector;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * @author will
 * @email zq2599@gmail.com
 * @date 2020-05-17 13:43
 * @description 体验KeyedProcessFunction类(时间类型是处理时间)
 */
public class ProcessTime {
   

    /**
     * KeyedProcessFunction的子类,作用是将每个单词最新出现时间记录到backend,并创建定时器,
     * 定时器触发的时候,检查这个单词距离上次出现是否已经达到10秒,如果是,就发射给下游算子
     */
    static class CountWithTimeoutFunction extends KeyedProcessFunction<Tuple, Tuple2<String, Integer>, Tuple2<String, Long>> {
   

        // 自定义状态
        private ValueState<CountWithTimestamp> state;

        @Override
        public void open(Configuration parameters) throws Exception {
   
            // 初始化状态,name是myState
            state = getRuntimeContext().getState(new ValueStateDescriptor<>("myState", CountWithTimestamp
  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flink提供了两种类型的定时器:事件时间定时器和处理时间定时器。 事件时间定时器基于事件时间,可以在数据流中插入一个事件时间戳,一旦到达指定时间,就会触发定时器。事件时间定时器适用于需要等待一段时间以获取完整结果的场景,例如处理窗口。 处理时间定时器基于处理时间,可以在数据到达后的固定时间间隔后触发定时器。处理时间定时器适用于需要在一定时间间隔内执行某个操作的场景,例如清理过期数据。 下面是一个使用处理时间定时器的示例代码: ``` DataStreamSource<String> source = env.fromElements("a", "b", "c"); source .map(new MapFunction<String, Tuple2<String, Long>>() { @Override public Tuple2<String, Long> map(String value) throws Exception { return Tuple2.of(value, System.currentTimeMillis() + 10000L); } }) .keyBy(0) .process(new KeyedProcessFunction<String, Tuple2<String, Long>, String>() { @Override public void processElement(Tuple2<String, Long> value, Context ctx, Collector<String> out) throws Exception { // 注册处理时间定时器,10秒后触发 ctx.timerService().registerProcessingTimeTimer(value.f1); // 保存状态 ValueState<String> state = getRuntimeContext().getState(new ValueStateDescriptor<>("value-state", String.class)); state.update(value.f0); } @Override public void onTimer(long timestamp, OnTimerContext ctx, Collector<String> out) throws Exception { // 处理时间定时器触发,输出状态中的值 ValueState<String> state = getRuntimeContext().getState(new ValueStateDescriptor<>("value-state", String.class)); out.collect(state.value()); } }) .print(); env.execute(); ``` 在上面的示例中,我们先从一个字符串数据源中获取数据,并使用MapFunction将每个字符串与当前时间戳组成一个Tuple2。然后,我们使用KeyedProcessFunction对每个Tuple2进行处理,其中我们注册了处理时间定时器,并将状态保存在ValueState中。当定时器触发时,我们可以从状态中获取值并输出。 需要注意的是,处理时间定时器的触发时间是相对于 Flink JobManager 的机器时间的,而不是相对于数据流中的事件时间。因此,在使用处理时间定时器时应特别注意处理时间与事件时间之间的差异。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值