flink:Apache Flink 一种流式计算框架,高吞吐低延迟的数据处理方案
原理:把所有数据视为流,由事件驱动,每次事件到达触发计算
与传统批处理的区别:Hadoop/Spark batch 固定数据集处理任务,任务所有逻辑执行完成一次提交
Hadoop优点:分布式文件存储,可动态组装数据库集群,实现高可靠、可容错、可扩展
可以把多台普通服务器集合成大数据集群,数据在每个节点上分别计算,最后汇总成完整数据
组成:
HDFS分布式文件系统-将数据拆分分别存在集群的不同节点上、通过副本机制保证数据安全
上传 300MB 文件 → 分成 3 个 block → 分布到 3 台机器上,每个 block 3 副本
包含两个关键角色:NameNode-元数据管理节点-记录数据所在的节点位置
DataNode-存储数据的节点
MapReduce分布式计算模型-在不同节点上进行不同数据的计算,最后归约汇总输出完整结果
两个阶段:Map-映射-分布式处理数据分片
Reduce-归约-汇总map输出
Yarn资源调度管理-集群资源调度管理、节点资源调度管理、单个应用的生命周期管理
使用场景:非实时性的离线数据任务(比如一些T+1更新的分析数据、离线日志分析)
主要使用场景:高实时性业务(监控告警、风控、推荐、广告投放、实时数仓)
在项目中集成flink-示例:动态统计5min内的点击数(强实时性统计,差一秒可能数据变更都非常大)
首先在pom中添加依赖 - 举例在kafka信息流中计算
java
<dependencies>
<!-- Flink 核心依赖 -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java</artifactId>
<version>1.18.1</version>
</dependency>
<!-- 如果需要 Kafka Source/Sink -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka</artifactId>
<version>1.18.1</version>
</dependency>
<!-- Spring Boot 基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>在这里插入代码片
注意:Flink 版本建议与生产集群一致,避免依赖冲突。
然后新建一个 Flink 任务类,例如 FlinkStreamJob.java:
java
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.connector.kafka.source.KafkaSource;
import org.apache.flink.connector.kafka.sink.KafkaSink;
import org.springframework.stereotype.Component;
@Component
public class FlinkStreamJob {
public void start() throws Exception {
// 1. 创建执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 2. 配置 Kafka Source - 从kafka读取数据流
KafkaSource<String> source = KafkaSource.<String>builder()
.setBootstrapServers("localhost:9092")
.setTopics("input-topic")
.setGroupId("flink-group")
.setValueOnlyDeserializer(new SimpleStringSchema())
.build();
DataStream<String> stream = env
.fromSource(source, WatermarkStrategy.noWatermarks(), "Kafka Source");
// 3. 数据转换逻辑
DataStream<String> result = stream
.map(value -> "Processed: " + value);
// 4. 输出到 Kafka Sink 将结果流输出到kafka去
KafkaSink<String> sink = KafkaSink.<String>builder()
.setBootstrapServers("localhost:9092")
.setRecordSerializer(KafkaRecordSerializationSchema.builder()
.setTopic("output-topic")
.setValueSerializationSchema(new SimpleStringSchema())
.build())
.build();
result.sinkTo(sink);
// 5. 启动作业
env.execute("SpringBoot-Flink-Job");
}
}
在springboot中集成这个任务
例如在 Application.java配置,启动SpringBoot应用时,Flink作业会自动运行
java
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.beans.factory.annotation.Autowired;
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
private FlinkStreamJob flinkJob;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... args) throws Exception {
flinkJob.start();
}
}
控制台输出类似:
Starting job SpringBoot-Flink-Job (JobID=xxxxxx)
Connected to Kafka source: input-topic
Producing to Kafka sink: output-topic
此时SpringBoot应用实际上已经成为一个可独立运行的 Flink 流任务服务
**
如果我创建了一个stream流式任务job,中间服务重启了,job会中断吗?
**
结论:如果是在springboot内集成的flink流,会中断,job会中断,内存状态丢失,重启后会重新从头计算
原因:此时flink是由springboot的jvm管理的,服务重启jvm会清空,对应的信息和状态就不存在了,就会中断计算逻辑,等待重启后重新开始
方案 1:启用 Checkpoint + Savepoint(推荐)
在代码中启用 Checkpoint,可以让 Flink 自动保存状态。
当任务重启时,会从最近的 Checkpoint 恢复,不中断计算结果的连续性。
示例:
java
env.enableCheckpointing(60000); // 每 60 秒做一次 checkpoint
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(30000);
env.getCheckpointConfig().setCheckpointTimeout(10000);
env.getCheckpointConfig().setMaxConcurrentCheckpoints(1);
// 可选:设置状态后端(例如 RocksDB 或 FileSystem)
env.setStateBackend(new HashMapStateBackend());
env.getCheckpointConfig().setCheckpointStorage("file:///tmp/flink-checkpoints");
效果:
即使服务重启,任务会在下次启动时自动从上次的 checkpoint 恢复
不会重复消费 Kafka
数据唯一不会重复处理
方案 2:把 Flink Job 运行在 独立集群中
即把 Flink Job 从 Spring Boot 进程中"独立"出来,
用 Spring Boot 作为 提交 / 监控 / 管理端。
运行方式:
flink run -c com.example.flinkdemo.job.FlinkKafkaJob
target/springboot-flink-demo-1.0.0.jar
优点:
Job 运行在 Flink 集群中;
不受 Spring Boot 重启影响;
可以自动从 checkpoint 恢复;
高可用 (HA) 可配置多个 JobManager。
Spring Boot 这时只做:
任务发布;
状态监控;
参数配置