9-Flink中的Time

本文深入探讨了Flink中的时间模型,包括事件时间(EventTime)、摄入时间(IngestionTime)和处理时间(ProcessingTime),并详细解释了各自的特点、应用场景及在分布式环境下的表现。文章还介绍了不同时间模型下窗口操作的实现方式,为读者提供了全面的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

戳原文:

1-Flink入门

2-本地环境搭建&构建第一个Flink应用

3-DataSet API 4-DataSteam API

5-集群部署

6-分布式缓存

7-重启策略

8-Flink中的窗口

9-Flink中的Time

时间

时间类型

  • Flink中的时间与现实世界中的时间是不一致的,在flink中被划分为事件时间,摄入时间,处理时间三种。

  • 如果以EventTime为基准来定义时间窗口将形成EventTimeWindow,要求消息本身就应该携带EventTime

  • 如果以IngesingtTime为基准来定义时间窗口将形成IngestingTimeWindow,以source的systemTime为准。

  • 如果以ProcessingTime基准来定义时间窗口将形成ProcessingTimeWindow,以operator的systemTime为准。

时间详解

Processing Time

Processing Time 是指事件被处理时机器的系统时间。

当流程序在 Processing Time 上运行时,所有基于时间的操作(如时间窗口)将使用当时机器的系统时间。每小时 Processing Time 窗口将包括在系统时钟指示整个小时之间到达特定操作的所有事件。

例如,如果应用程序在上午 9:15 开始运行,则第一个每小时 Processing Time 窗口将包括在上午 9:15 到上午 10:00 之间处理的事件,下一个窗口将包括在上午 10:00 到 11:00 之间处理的事件。

Processing Time 是最简单的 “Time” 概念,不需要流和机器之间的协调,它提供了最好的性能和最低的延迟。但是,在分布式和异步的环境下,Processing Time 不能提供确定性,因为它容易受到事件到达系统的速度(例如从消息队列)、事件在系统内操作流动的速度以及中断的影响。

Event Time

Event Time 是事件发生的时间,一般就是数据本身携带的时间。这个时间通常是在事件到达 Flink 之前就确定的,并且可以从每个事件中获取到事件时间戳。在 Event Time 中,时间取决于数据,而跟其他没什么关系。Event Time 程序必须指定如何生成 Event Time 水印,这是表示 Event Time 进度的机制。

完美的说,无论事件什么时候到达或者其怎么排序,最后处理 Event Time 将产生完全一致和确定的结果。但是,除非事件按照已知顺序(按照事件的时间)到达,否则处理 Event Time 时将会因为要等待一些无序事件而产生一些延迟。由于只能等待一段有限的时间,因此就难以保证处理 Event Time 将产生完全一致和确定的结果。

假设所有数据都已到达, Event Time 操作将按照预期运行,即使在处理无序事件、延迟事件、重新处理历史数据时也会产生正确且一致的结果。 例如,每小时事件时间窗口将包含带有落入该小时的事件时间戳的所有记录,无论它们到达的顺序如何。

请注意,有时当 Event Time 程序实时处理实时数据时,它们将使用一些 Processing Time 操作,以确保它们及时进行。

Ingestion Time

Ingestion Time 是事件进入 Flink 的时间。 在源操作处,每个事件将源的当前时间作为时间戳,并且基于时间的操作(如时间窗口)会利用这个时间戳。

Ingestion Time 在概念上位于 Event Time 和 Processing Time 之间。 与 Processing Time 相比,它稍微复杂一些,但结果更可预测。因为 Ingestion Time 使用稳定的时间戳(在源处分配一次),所以对事件的不同窗口操作将引用相同的时间戳,而在 Processing Time 中,每个窗口操作符可以将事件分配给不同的窗口(基于机器系统时间和到达延迟)。

与 Event Time 相比,Ingestion Time 程序无法处理任何无序事件或延迟数据,但程序不必指定如何生成水印。

在 Flink 中,,Ingestion Time 与 Event Time 非常相似,但 Ingestion Time 具有自动分配时间戳和自动生成水印功能。

公众号推荐

  • 全网唯一一个从0开始帮助Java开发者转做大数据领域的公众号,BAT团队集体开发~
  • 海量【java和大数据的面试题+视频资料】整理在公众号,关注后可以下载~
  • 更多大数据技术欢迎和作者一起探讨~

<think>我们之前讨论的是在Kubernetes中使用Flink Operator部署Flink程序。现在,用户澄清了“stage-analysis-flink-gameonline-gyyx-cn”是一个使用Flink的业务Pod,而不是Flink集群本身。因此,我们需要调整思路:这个Pod可能是运行Flink作业的客户端,或者是Flink集群中的一个组件(如JobManager或TaskManager)。但根据名称,它更可能是一个运行Flink作业的Pod(可能是通过Flink Client提交作业,或者是作为Flink集群的一部分)。 然而,在Kubernetes环境中,通常使用Flink Operator来管理整个Flink集群(包括JobManager和TaskManager)。用户提到“使用Flink Operator”,所以我们可以假设这个业务Pod是Flink集群的一部分,或者是由Flink Operator管理的作业。 考虑到用户提供的信息,我们重新梳理: 1. **腾讯云CFS**:10.14.84.131,用于共享存储,如Flink的savepoints、检查点等。 2. **Kubernetes命名空间**:dlyy-master 3. **业务Pod名称**:stage-analysis-flink-gameonline-gyyx-cn 在Flink on Kubernetes的两种模式: - **Session集群**:预先启动一个Flink集群,然后提交作业(作业运行在TaskManager上)。 - **Application模式**:每个作业启动一个专属集群(包含JobManager和TaskManager),作业完成后集群销毁。 用户使用了Flink Operator,所以通常是通过自定义资源`FlinkDeployment`来定义作业。 因此,我们可以认为`stage-analysis-flink-gameonline-gyyx-cn`这个名称实际上对应的是FlinkDeployment资源,而该资源会创建一组Pod(包括JobManager和TaskManager)。用户可能看到的是其中一个Pod(比如JobManager Pod)。 ### 解决方案:使用Flink Operator部署Flink作业 我们将提供一个完整的FlinkDeployment配置,该配置将创建一个Flink集群(包括JobManager和TaskManager),并运行指定的作业。同时,我们将使用腾讯云CFS作为持久化存储。 #### 步骤1:安装Flink Operator 在集群上安装Flink Operator(如果尚未安装)。这里我们使用Helm进行安装(假设已安装Helm): ```bash helm repo add flink-operator https://googlecloudplatform.github.io/flink-on-k8s-operator/ helm install flink-operator flink-operator/flink-operator --namespace flink-operator --create-namespace --version=1.7.0 ``` #### 步骤2:创建持久卷(PV)和持久卷声明(PVC) 使用腾讯云CFS创建PV和PVC,供Flink集群使用。 ```yaml # cfs-pv-pvc.yaml apiVersion: v1 kind: PersistentVolume metadata: name: flink-cfs-pv namespace: dlyy-master spec: capacity: storage: 100Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: cfs nfs: server: 10.14.84.131 path: "/flink_data" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: flink-cfs-pvc namespace: dlyy-master spec: storageClassName: cfs accessModes: - ReadWriteMany resources: requests: storage: 100Gi ``` 应用配置: ```bash kubectl apply -f cfs-pv-pvc.yaml -n dlyy-master ``` #### 步骤3:创建FlinkDeployment 定义Flink作业,使用上面创建的PVC。 ```yaml # flink-deployment.yaml apiVersion: flink.apache.org/v1beta1 kind: FlinkDeployment metadata: name: stage-analysis-flink-gameonline-gyyx-cn namespace: dlyy-master spec: image: flink:1.16.1 # Flink基础镜像 flinkVersion: v1_16 serviceAccount: flink-service-account # 需要提前创建服务账号并授权 podTemplate: spec: containers: - name: flink-main-container volumeMounts: - name: checkpoint-volume mountPath: /opt/flink/checkpoints volumes: - name: checkpoint-volume persistentVolumeClaim: claimName: flink-cfs-pvc jobManager: resource: memory: "2048m" cpu: 1 taskManager: resource: memory: "4096m" cpu: 2 replicas: 4 # TaskManager的数量 job: jarURI: "local:///opt/flink/jobs/game-analysis.jar" # 作业JAR包路径,需要预先放入镜像,或者通过initContainer下载 entryClass: "com.tencent.gyyx.GameOnlineAnalysis" args: ["--kafka.brokers", "kafka-service:9092"] # 作业参数 parallelism: 8 upgradeMode: savepoint # 升级策略 initialState: new # 初始状态:新作业 ``` #### 步骤4:部署Flink作业 应用FlinkDeployment: ```bash kubectl apply -f flink-deployment.yaml -n dlyy-master ``` ### 关键点说明 1. **镜像**:使用官方Flink镜像,但需要确保镜像中包含作业的JAR包。有两种方式: -定义Docker镜像,将JAR包放入镜像中(推荐)。 - 使用Init Container从远程存储下载JAR包到共享卷,然后挂载到容器。 2. **服务账号**:需要创建一个服务账号`flink-service-account`,并授予必要的权限(如管理Pod、ConfigMap等)。Flink Operator需要这些权限来管理Pod。 3. **存储**:将腾讯云CFS挂载到`/opt/flink/checkpoints`,用于保存检查点和保存点。 4. **作业参数**:通过`args`传递作业需要的参数,如Kafka broker地址。 ### 验证部署 - 查看FlinkDeployment状态: ```bash kubectl get flinkdeployment -n dlyy-master ``` - 查看Pod: ```bash kubectl get pods -n dlyy-master | grep stage-analysis-flink-gameonline-gyyx-cn ``` 应该会看到JobManager和TaskManager的Pod。 - 查看日志: ```bash kubectl logs -f stage-analysis-flink-gameonline-gyyx-cn-jobmanager-xxxx -n dlyy-master ``` ### 自定义镜像示例 如果作业需要额外的依赖,可以构建自定义镜像。例如,Dockerfile: ```dockerfile FROM flink:1.16.1 # 将作业JAR包和依赖放入镜像 COPY game-analysis.jar /opt/flink/jobs/ ``` 构建并推送到镜像仓库,然后在FlinkDeployment中指定镜像。 §§相关问题§§: 1. 如何为Flink作业配置高可用(HA)? 2. 如何从Savepoint恢复Flink作业? 3. 如何监控运行在Kubernetes上的Flink作业? 4. 如何调整Flink作业的并行度?</think>### 深入理解:业务 Pod `stage-analysis-flink-gameonline-gyyx-cn` 的 Flink 实现 您提到的 `stage-analysis-flink-gameonline-gyyx-cn` 是一个运行 Flink 作业的业务 Pod。在 Kubernetes 环境中,这通常是通过 Flink Operator 部署的 Flink 作业集群中的 TaskManager 或 JobManager 实例。以下是完整的实现方案: #### 核心架构解析 ```mermaid graph LR A[腾讯云CFS] --> B[Flink JobManager] A --> C[Flink TaskManager] B --> D[业务逻辑] C --> D D --> E[(Kafka)] D --> F[(Redis)] D --> G[(MySQL)] ``` #### 完整 Flink 作业代码实现 ```java // GameOnlineAnalysis.java import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.api.common.functions.RichMapFunction; import org.apache.flink.configuration.Configuration; public class GameOnlineAnalysis { public static void main(String[] args) throws Exception { final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 从Kafka读取游戏事件流 DataStream<GameEvent> events = env .addSource(new FlinkKafkaConsumer<>( "game-events", new GameEventDeserializer(), properties)) .name("kafka-source"); // 实时计算在线玩家状态 DataStream<PlayerStatus> statusStream = events .keyBy(Player::getId) .map(new PlayerStatusMapper()) .name("player-status-mapper"); // 窗口统计在线人数 DataStream<OnlineStats> statsStream = statusStream .window(TumblingEventTimeWindows.of(Time.minutes(5))) .aggregate(new OnlineCounter()) .name("online-counter"); // 输出到Redis和MySQL statsStream.addSink(new RedisSink()); statsStream.addSink(new JdbcSink()); env.execute("Game Online Real-time Analysis"); } // 自定义反序列化器 public static class GameEventDeserializer implements KafkaDeserializationSchema<GameEvent> { @Override public GameEvent deserialize(ConsumerRecord<byte[], byte[]> record) { // 解析JSON数据 return JSON.parse(record.value(), GameEvent.class); } } // 玩家状态映射 public static class PlayerStatusMapper extends RichMapFunction<GameEvent, PlayerStatus> { private transient ValueState<PlayerStatus> statusState; @Override public void open(Configuration parameters) { ValueStateDescriptor<PlayerStatus> descriptor = new ValueStateDescriptor<>("playerStatus", PlayerStatus.class); statusState = getRuntimeContext().getState(descriptor); } @Override public PlayerStatus map(GameEvent event) { PlayerStatus current = statusState.value(); if (current == null) current = new PlayerStatus(); // 更新状态逻辑 if (event.getType() == EventType.LOGIN) { current.setOnline(true); current.setLastLogin(event.getTimestamp()); } else if (event.getType() == EventType.LOGOUT) { current.setOnline(false); current.setLastLogout(event.getTimestamp()); } statusState.update(current); return current; } } } ``` #### Kubernetes 部署配置优化 ```yaml # flink-deployment.yaml apiVersion: flink.apache.org/v1beta1 kind: FlinkDeployment metadata: name: stage-analysis-flink-gameonline-gyyx-cn namespace: dlyy-master spec: image: custom-flink:1.16.1-gyyx # 包含业务代码的自定义镜像 flinkVersion: v1_16 serviceAccount: flink-service-account podTemplate: metadata: annotations: tencent.com/cfs: "enabled" spec: containers: - name: flink-main-container env: - name: KAFKA_BROKERS value: "kafka-service:9092" - name: REDIS_HOST value: "redis-master" volumeMounts: - name: cfs-volume mountPath: /opt/flink/checkpoints - name: config-volume mountPath: /opt/flink/conf/flink-conf.yaml subPath: flink-conf.yaml volumes: - name: cfs-volume persistentVolumeClaim: claimName: flink-cfs-pvc - name: config-volume configMap: name: flink-config --- # flink-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: flink-config namespace: dlyy-master data: flink-conf.yaml: | # 关键性能参数 taskmanager.memory.process.size: 4096m taskmanager.numberOfTaskSlots: 4 parallelism.default: 8 state.backend: filesystem state.checkpoints.dir: file:///opt/flink/checkpoints state.savepoints.dir: file:///opt/flink/savepoints execution.checkpointing.interval: 5min execution.checkpointing.mode: EXACTLY_ONCE ``` #### 关键优化点说明 1. **状态管理优化**: ```java // 使用ValueState管理玩家状态 ValueStateDescriptor<PlayerStatus> descriptor = new ValueStateDescriptor<>("playerStatus", PlayerStatus.class); statusState = getRuntimeContext().getState(descriptor); ``` - 利用 Flink 的状态后端将玩家状态持久化到 CFS - 支持故障恢复时精确恢复玩家状态 2. **检查点配置**: ```yaml state.backend: filesystem state.checkpoints.dir: file:///opt/flink/checkpoints execution.checkpointing.interval: 5min ``` - 每 5 分钟创建一次检查点 - 检查点存储在腾讯云 CFS 上,保证可靠性 3. **资源隔离**: ```yaml taskmanager.memory.process.size: 4096m taskmanager.numberOfTaskSlots: 4 ``` - 每个 TaskManager 配置 4 个 slot - 4GB 内存分配,避免 OOM #### 运维监控脚本 ```bash #!/bin/bash # 获取Flink作业状态 JOB_ID=$(kubectl exec -n dlyy-master \ deployment/stage-analysis-flink-gameonline-gyyx-cn-jobmanager \ -- curl -s http://localhost:8081/jobs | jq -r &#39;.jobs[0]&#39;) # 触发保存点 kubectl exec -n dlyy-master \ deployment/stage-analysis-flink-gameonline-gyyx-cn-jobmanager \ -- curl -X POST http://localhost:8081/jobs/$JOB_ID/savepoints # 检查点状态监控 kubectl exec -n dlyy-master \ deployment/stage-analysis-flink-gameonline-gyyx-cn-jobmanager \ -- curl -s http://localhost:8081/jobs/$JOB_ID/checkpoints ``` ### 部署流程 1. **构建自定义镜像**: ```dockerfile FROM flink:1.16.1 ADD target/game-analysis.jar /opt/flink/jobs/ COPY conf/log4j.properties /opt/flink/conf/ ``` 2. **部署到 Kubernetes**: ```bash # 创建配置 kubectl create configmap flink-config -n dlyy-master --from-file=flink-conf.yaml # 部署Flink集群 kubectl apply -f flink-deployment.yaml -n dlyy-master # 验证部署 kubectl get pods -n dlyy-master -l app=stage-analysis-flink-gameonline-gyyx-cn ``` 3. **日志检查**: ```bash kubectl logs -f -n dlyy-master \ deployment/stage-analysis-flink-gameonline-gyyx-cn-jobmanager ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值