「Flink」事件时间与水印
我们先来以滚动时间窗口为例,来看一下窗口的几个时间参数与Flink流处理系统时间特性的关系。
获取窗口开始时间Flink源代码
获取窗口的开始时间为以下代码:
org.apache.flink.streaming.api.windowing.windows.TimeWindow
/**
* Method to get the window start for a timestamp.
*
* @param timestamp epoch millisecond to get the window start.
* @param offset The offset which window start would be shifted by.
* @param windowSize The size of the generated windows.
* @return window start
*/
public static long getWindowStartWithOffset(long timestamp, long offset, long windowSize) {
return timestamp - (timestamp - offset + windowSize) % windowSize;
}
这一段代码,我们可以认为Flink并不是把时间戳直接作为窗口的开始时间,而是做了一些“对齐”操作,确保时间能够整除8。
不同时间类型的窗口时间计算
1、当TimeCharacteristic为ProcessingTime时
窗口的开始时间:与窗口接收到的第一条消息的处理时间有关。例如:window operator是2020-02-06 22:02:33接收到的第一条消息,那么窗口的开始时间就是2020-02-06 22:02:33。
窗口的结束时间:一旦窗口的开始时间确定了,因为窗口的长度是固定的。那么窗口的结束时间就确定下来了,例如:假设这里的时间窗口是3秒,那么窗口的结束时间就是2020-02-06 22:02:36。
窗口的触发计算时间:假设有一条新的消息到达window operator,此时如果对应operator的系统时间,大于结束时间,就会触发计算。
一旦窗口的开始时间确定了,那么后续窗口的开始时间,也就都确定下来了。
问题:
假设某个时间窗口,2020-2-6 22:12:20 - 2020-2-6 22:12:23,之间没有任何一条数据进来。Flink会如何处理?
Flink会直接抛弃掉这个时间窗口,新来的事件消息会到其他的时间窗口中计算。
2、当TimeCharacteristic为IngestionTime时
窗口的开始时间:与source operator接收到的第一条消息有关。例如:source接收到这条消息的时间是2020-2-6 22:14:50,那么窗口的开始时间就是2020-2-6 22:14:50
窗口的结束时间:与ProcessTime一致
窗口的触发计算时间:假设有一条新的消息到达source operator,那么此时的时间如果大于结束时间,就会触发计算。
除了窗口的开始时间、触发时间都是与source operator算子有关,其他与Processing Time是类似的。
3、但TimeCharacteristic为EventTime时
窗口的开始时间:与window operator接收到的第一条消息的事件时间有关,例如:如果这条消息的水印时间是2020-2-6 22:17:50,那么窗口的的开始时间就是2020-2-6 22:17:50
窗口的结束时间:与ProcessTime一致
窗口的触发计算时间:假设有一条新的消息到达window operator,如果该事件的水印时间大于窗口的结束时间,就会触发计算。
通常,我们会让水印时间比事件时间允许延迟几秒钟。这样,如果是因为网络延迟消息晚到了几秒,也不会影响到统计结果了。
public class WordCountWindow {
public static void main(String[] args) throws Exception {
// 1. 初始化流式运行环境
Configuration conf = new Configuration();
StreamExecutionEnvironment env = StreamExecutionEnvironment.createLocalEnvironmentWithWebUI(conf);
// 2. 设置时间处理类型,这里设置的方式处理时间
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
// 3. 定义数据源,每秒发送一个hadoop单词
SingleOutputStreamOperator<Tuple2<String, Long>> wordDSWithWaterMark = env.addSource(new RichSourceFunction<Tuple2<String, Long>>() {
private boolean isCanaled = false;
private int TOTAL_NUM = 20;
@Override
public void run(SourceContext<Tuple2<String, Long>> ctx) throws Exception {
while (!isCanaled) {
ctx.collect(Tuple2.of("hadooop", System.currentTimeMillis()));
// 打印窗口开始、结束时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("事件发送时间:" + sdf.format(System.currentTimeMillis()));
Thread.sleep(1000);
}
}
@Override
public void cancel() {
isCanaled = true;
}
}).assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<Tuple2<String, Long>>(Time.seconds(5)) {
@Override
public long extractTimestamp(Tuple2<String, Long> element) {
return element.f1;
}
});
// 4. 每5秒进行一次,分组统计
// 4.1 转换为元组
wordDSWithWaterMark.map(word -> {
return Tuple2.of(word.f0, 1);
})
// 指定返回类型
.returns(Types.TUPLE(Types.STRING, Types.INT))
// 按照单词进行分组
.keyBy(t -> t.f0)
// 滚动窗口,3秒计算一次
.timeWindow(Time.seconds(3))
.reduce(new ReduceFunction<Tuple2<String, Integer>>() {
@Override
public Tuple2<String, Integer> reduce(Tuple2<String, Integer> value1, Tuple2<String, Integer> value2) throws Exception {
return Tuple2.of(value1.f0, value1.f1 + value2.f1);
}
}, new RichWindowFunction<Tuple2<String, Integer>, Tuple2<String, Integer>, String, TimeWindow>() {
@Override
public void apply(String word, TimeWindow window, Iterable<Tuple2<String, Integer>> input, Collector<Tuple2<String, Integer>> out) throws Exception {
// 打印窗口开始、结束时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("窗口开始时间:" + sdf.format(window.getStart())
+ " 窗口结束时间:" + sdf.format(window.getEnd())
+ " 窗口计算时间:" + sdf.format(System.currentTimeMillis()));
int sum = 0;
Iterator<Tuple2<String, Integer>> iterator = input.iterator();
while(iterator.hasNext()) {
Integer count = iterator.next().f1;
sum += count;
}
out.collect(Tuple2.of(word, sum));
}
}).print();
env.execute("app");
}
}
输出结果如下:
事件发送时间:2020-02-06 22:35:08
事件发送时间:2020-02-06 22:35:09
事件发送时间:2020-02-06 22:35:10
事件发送时间:2020-02-06 22:35:11
事件发送时间:2020-02-06 22:35:12
事件发送时间:2020-02-06 22:35:13
事件发送时间:2020-02-06 22:35:14
窗口开始时间:2020-02-06 22:35:06 窗口结束时间:2020-02-06 22:35:09 窗口计算时间:2020-02-06 22:35:14
4> (hadooop,1)事件发送时间:2020-02-06 22:35:15
事件发送时间:2020-02-06 22:35:16
事件发送时间:2020-02-06 22:35:17
窗口开始时间:2020-02-06 22:35:09 窗口结束时间:2020-02-06 22:35:12 窗口计算时间:2020-02-06 22:35:17
4> (hadooop,3)
参考文件:
https://ci.apache.org/projects/flink/flink-docs-release-1.9/zh/dev/event_time.html
「Flink」事件时间与水印的更多相关文章
- Flink基础:时间和水印
往期推荐: Flink基础:入门介绍 Flink基础:DataStream API Flink基础:实时处理管道与ETL Flink深入浅出:资源管理 Flink深入浅出:部署模式 Flink深入 ...
- 第08讲:Flink 窗口、时间和水印
Flink系列文章 第01讲:Flink 的应用场景和架构模型 第02讲:Flink 入门程序 WordCount 和 SQL 实现 第03讲:Flink 的编程模型与其他框架比较 第04讲:Flin ...
- 「Flink」Flink中的时间类型
Flink中的时间类型和窗口是非常重要概念,是学习Flink必须要掌握的两个知识点. Flink中的时间类型 时间类型介绍 Flink流式处理中支持不同类型的时间.分为以下几种: 处理时间 Flink ...
- 「Flink」理解流式处理重要概念
什么是流式处理呢? 这个问题其实我们大部分时候是没有考虑过的,大多数,我们是把流式处理和实时计算放在一起来说的.我们先来了解下,什么是数据流. 数据流(事件流) 数据流是无边界数据集的抽象 我们之前接 ...
- 「Flink」Flink的状态管理与容错
在Flink中的每个函数和运算符都是有状态的.在处理过程中可以用状态来存储数据,这样可以利用状态来构建复杂操作.为了让状态容错,Flink需要设置checkpoint状态.Flink程序是通过chec ...
- 「Flink」RocksDB介绍以及Flink对RocksDB的支持
RocksDB介绍 RocksDB简介 RocksDB是基于C++语言编写的嵌入式KV存储引擎,它不是一个分布式的DB,而是一个高效.高性能.单点的数据库引擎.它是由Facebook基于Google开 ...
- 「Flink」Flink 1.9 WebUI运行作业界面分析
运行作业界面 在以下界面中,可以查看到作业的名称.作业的启动时间.作业总计运行时长.作业一共有多少个任务.当前正在运行多少个任务.以及作业的当前状态. 这里的程序:一共有17个任务,当前正在运行的是1 ...
- 「Flink」配置使用Flink调试WebUI
很多时候,我们在IDE中编写Flink代码,我们希望能够查看到Web UI,从而来了解Flink程序的运行情况.按照以下步骤操作即可,亲测有效. 1.添加Maven依赖 <dependency& ...
- 「Flink」使用Managed Keyed State实现计数窗口功能
先上代码: public class WordCountKeyedState { public static void main(String[] args) throws Exception { S ...
随机推荐
- c++ 文件的简单操作
文件的读取操作 在程序设计中,文件常用的操作不外乎--打开.读.写.流指针操作.关闭.我日常中使用的比较多,但从来 没有细细总结今天就总结下具体的用法. 相关概念 计算机上的文件其实是数据的集合,对文 ...
- vwmare 十月第 1 弹
step one 不管 是 ubuntu 还是 win vm tools 都是需要在虚拟的系统里面的去安装的. 这一点是相同的.
- [校内训练19_09_02]C
题意 给出一棵N 个节点的树,树上的每个节点都有一个权值$a_i$. 有Q 次询问,每次在树上选中两个点u, v,考虑所有在简单路径u, v 上(包括u, v)的点构成的集合S. 求$\sum_{w∈ ...
- volatile梳理
volatile 可见性也就是说一旦某个线程修改了该被volatile修饰的变量,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,可以立即获取修改之后的值. 在Java中为了加快程序的运行 ...
- RabbitMq 深入了解
积少成多 ---- 仅以此致敬和我一样在慢慢前进的人儿 问题一:什么是RabbitMq 下面就是些个人的感受, rabbitmq 就是一个遵循AMQP协议(这个是啥不清楚) 的消息队列的实现,用于服 ...
- 在Centos上安装docker,部署mysql数据库
何为docker? Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化. 本机环境 24小时不关机的Centos ...
- [python]Mongodb
文档: http://api.mongodb.com/python/current/tutorial.html 安装: 官网直接下载安装, mac上brew安装的下载太慢, 打算手动安装 使用: 开启 ...
- Open Images V4 下载自己需要的类别
OpenImages V4数据集描述1)这个v4数据集主要有两种用途:对象检测及分类,意思是说可以用这个数据集训练出对象检测模型,用于识别图像中的对象类别及位置边框.视觉关系检测,比如你用这个v4数据 ...
- 浅谈ActionResult之FileResult
FileResult是一个基于文件的ActionResult,利用FileResult,我们可以很容易的将某个物理文件的内容响应给客户端,ASP.NET MVC定义了三个具体的FileResult,分 ...
- JMeter+Grafana+Influxdb搭建可视化性能测试监控平台(待继续完善。。。)
influxdb下载.安装.配置.启动 InfluxDB是一个当下比较流行的时序数据库,InfluxDB使用 Go 语言编写,无需外部依赖,安装配置非常方便,适合构建大型分布式系统的监控系统. 下载: ...