Flink+Kafka构建实时数据架构:原理+实践+调优,万字长文详解
元数据框架
标题:Flink+Kafka构建实时数据架构:原理深度解析、实践落地指南与性能调优全攻略关键词:实时数据架构, Flink流处理, Kafka消息队列, Exactly-Once语义, 状态管理, 性能调优, 云原生摘要:
随着大数据与人工智能的爆发,实时数据架构已成为企业实现快速决策的核心支撑。本文以”Flink+Kafka”组合为核心,从概念基础、理论框架、架构设计、实现机制、实践落地到高级考量,全面拆解实时数据架构的底层逻辑。通过第一性原理推导、数学形式化分析与真实案例验证,揭示Flink(精准计算)与Kafka(高效传输)的协同机制,并提供可落地的部署策略、代码优化与性能调优指南。无论是入门者还是资深工程师,都能从本文中获得系统的知识体系与实践启发。
1. 概念基础:实时数据架构的核心语境
1.1 领域背景化:为什么需要实时数据架构?
在传统批处理时代(如Hadoop),数据处理延迟以小时/天为单位,无法满足实时决策需求(如电商实时推荐、金融实时风控、物流实时跟踪)。随着5G、IoT、AI技术的普及,企业需要毫秒级处理无限数据流,实时数据架构应运而生。
核心需求:
低延迟(Latency):数据从产生到结果输出的时间≤1秒;高吞吐(Throughput):支持百万级/秒的数据流处理;Exactly-Once(精确一次):数据不丢失、不重复;可扩展性(Scalability):动态适应数据量增长;容错性(Fault Tolerance):节点故障后快速恢复。
1.2 历史轨迹:Flink与Kafka的协同演化
| 时间 | 事件 |
|---|---|
| 2011年 | LinkedIn开源Kafka,解决流数据传输的高吞吐、低延迟问题 |
| 2014年 | Apache Flink成为顶级项目,专注流计算的Exactly-Once与状态管理 |
| 2016年 | Flink 1.0发布,支持Kafka 0.10+版本的Exactly-Once集成 |
| 2021年 | Kafka 3.0引入KRaft模式(替代ZooKeeper),提升元数据管理性能 |
| 2023年 | Flink 1.18增强K8s支持,推动实时架构向云原生演进 |
1.3 问题空间定义:实时数据架构的核心挑战
数据传输:如何高效存储与传输无限数据流?(Kafka解决)数据计算:如何精准处理有状态的实时流?(Flink解决)语义保证:如何确保数据处理的Exactly-Once?(Flink+Kafka协同解决)资源管理:如何平衡计算资源与处理性能?(架构设计与调优解决)
1.4 术语精确性:避免概念混淆
| 术语 | 定义 |
|---|---|
| 流处理(Stream Processing) | 处理无限、连续的数据流,输出实时结果(如Flink) |
| 批处理(Batch Processing) | 处理有限、静态的数据集,输出离线结果(如Hadoop) |
| Topic | Kafka中的消息类别,类似数据库的”表”,用于分类存储数据流 |
| Partition | Topic的分片,用于并行处理(每个Partition是有序日志,支持多副本) |
| Offset | 消息在Partition中的位置指针,消费者通过Offset跟踪消费进度 |
| 算子(Operator) | Flink中的数据处理单元(如Map、Filter、Window),构成数据流的”管道” |
| 状态(State) | Flink算子保存的中间结果(如计数器、窗口聚合值),支持有状态计算 |
| Checkpoint | Flink的容错机制,通过分布式快照保存算子状态与Kafka Offset,实现故障恢复 |
2. 理论框架:Flink+Kafka的协同原理
2.1 第一性原理推导:实时架构的核心逻辑
实时数据架构的本质是**“高效传输” + “精准计算”**的组合:
高效传输:Kafka通过Partition模型(并行存储)、日志结构(追加写入)、副本机制(高可用)满足高吞吐、低延迟需求;精准计算:Flink通过数据流模型(无限流处理)、状态管理(有状态计算)、Checkpoint(容错)满足Exactly-Once与低延迟需求。
2.2 数学形式化:核心模型的量化分析
2.2.1 Kafka的Partition模型
假设Topic有个Partition,每个Partition的消息数为
P,则总消息数为
M。
Total = P × M
消费者数量需满足:
C(每个Partition由一个消费者处理,避免并行度浪费)。
C ≥ P
吞吐量公式:(每个Partition的吞吐量取决于磁盘IO)。
Throughput = P × (Messages/Second per Partition)
2.2.2 Flink的窗口计算模型
对于滚动窗口(Tumbling Window),窗口大小为(秒),事件时间为
W,则窗口起始时间为:
t
2.2.3 Exactly-Once语义的数学保证
Flink的Checkpoint机制通过Chandy-Lamport算法实现分布式快照,保存:
算子的状态();Kafka消费者的Offset(
State)。
Offset
恢复时,从Checkpoint中读取与
State,确保:
Offset
3.1.1 数据采集层:从数据源到Kafka
职责:采集分散的数据源(数据库、日志、传感器),转换为标准格式(JSON/Protobuf),发送到Kafka Topic。
工具选择:
CDC(变更数据捕获):Debezium(支持MySQL/PostgreSQL)、Canal(阿里巴巴开源,专注MySQL);日志采集:Logstash(ELK生态)、Fluentd(云原生优先);IoT数据:MQTT Broker(如EMQ X)。
3.1.2 数据传输层:Kafka的核心角色
职责:作为”数据总线”,存储与传输实时数据流,实现采集层与计算层的解耦。
核心设计:
Topic规划:按业务类型划分(如、
order-topic);Partition设置:根据吞吐量需求,每个Topic设置3-10个Partition(如
user-behavior-topic设为5个Partition);副本策略:每个Partition设置2-3个副本(如
order-topic),确保高可用。
replication-factor=2
3.1.3 数据计算层:Flink的计算逻辑
职责:对Kafka中的数据流进行实时处理(ETL、聚合、机器学习推理)。
核心组件:
JobManager:负责作业调度、Checkpoint管理;TaskManager:负责执行算子任务(每个TaskManager有多个Slot,用于并行处理);算子链:Flink将相邻算子(如Map+Filter)合并为一个算子链,减少数据传输开销。
3.1.4 数据存储层:实时结果的持久化
职责:存储Flink计算后的结果,支持快速查询与访问。
工具选择:
实时计数器:Redis(内存数据库,支持高并发读写);日志分析:Elasticsearch(全文检索,支持复杂查询);海量数据:HBase(列族数据库,支持随机读写);实时分析:ClickHouse(列式数据库,支持高吞吐查询)。
3.1.5 数据服务层:从存储到应用
职责:将存储层的数据转换为可消费的服务(如Dashboard、API)。
工具选择:
可视化:Grafana(支持Redis、Elasticsearch等数据源,实时Dashboard);API:Spring Boot(开发RESTful API,供前端应用调用);BI工具:Tableau(支持实时数据连接,生成报表)。
3.2 组件交互:数据流的生命周期
以电商实时订单分析为例,数据流的生命周期如下:
采集:Debezium从MySQL的表采集insert事件,转换为JSON(如
order),发送到
{"order_id": "123", "amount": 100.0};传输:Kafka将
order-topic的消息存储到5个Partition(每个Partition有2个副本);计算:Flink消费
order-topic,解析JSON提取
order-topic,用5秒滚动窗口计算总销售额(
amount);存储:Flink将总销售额写入Redis的
sum(amount)键;服务:Grafana从Redis读取
total_sales,实时展示销售额曲线。
total_sales
3.3 设计模式:复用与优化
3.3.1 生产者-消费者模式(Kafka)
Kafka的生产者(采集层)将消息发送到Topic,消费者(Flink)从Topic拉取消息,实现解耦与异步处理。
优势:生产者与消费者无需感知对方的存在,支持动态扩展。
3.3.2 算子链模式(Flink)
Flink将相邻的无状态算子(如Map+Filter)合并为一个算子链,减少网络传输与线程切换的开销。
示例:
DataStream<String> stream = env.addSource(kafkaConsumer)
.map(new MapFunction<String, String>() { ... }) // 解析JSON
.filter(new FilterFunction<String>() { ... }) // 过滤无效订单
.keyBy(...) // 按用户分组
.window(...) // 窗口计算
.sum(...) // 聚合
.addSink(redisSink); // 写入Redis
(Flink会自动将与
map合并为一个算子链)
filter
3.3.3 快照模式(Flink Checkpoint)
Flink通过分布式快照保存算子状态与Kafka Offset,实现容错。
流程:
JobManager向所有TaskManager发送Checkpoint触发信号;TaskManager将算子状态写入Checkpoint存储(如HDFS、S3);Kafka消费者将当前Offset写入Checkpoint;所有TaskManager完成快照后,JobManager标记Checkpoint为完成。
4. 实现机制:代码与性能的底层逻辑
4.1 算法复杂度:关键操作的效率
4.1.1 Kafka生产者发送消息
时间复杂度:(追加到Partition的日志末尾);优化点:设置
O(1)(批量发送大小,默认16KB)、
batch.size(等待时间,默认0ms),合并小批量消息,提高吞吐量。
linger.ms
4.1.2 Kafka消费者拉取消息
时间复杂度:(根据Offset定位消息);优化点:设置
O(1)(每次拉取的最小字节数,默认1B)、
fetch.min.bytes(最大等待时间,默认500ms),减少拉取次数。
fetch.max.wait.ms
4.1.3 Flink窗口计算
时间复杂度:(
O(n)为窗口内的消息数);优化点:使用增量聚合(如
n)替代全量聚合(如
ReduceFunction),减少内存占用。
AggregateFunction
4.2 优化代码实现:生产级实践
4.2.1 Kafka消费者优化(Flink端)
Properties kafkaProps = new Properties();
kafkaProps.setProperty("bootstrap.servers", "kafka:9092");
kafkaProps.setProperty("group.id", "flink-consumer-group");
kafkaProps.setProperty("auto.offset.reset", "earliest"); // 从最早Offset开始消费
kafkaProps.setProperty("enable.auto.commit", "false"); // 关闭自动提交,由Flink管理
// 创建FlinkKafkaConsumer(支持Exactly-Once)
FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>(
"order-topic", // Topic名称
new SimpleStringSchema(), // 序列化器(JSON)
kafkaProps // 配置
);
// 设置Offset提交策略(与Checkpoint同步)
consumer.setCommitOffsetsOnCheckpoints(true);
// 添加Source到Flink
DataStream<String> orderStream = env.addSource(consumer);
4.2.2 Flink状态管理优化
// 选择状态后端(RocksDB适合大状态)
env.setStateBackend(new RocksDBStateBackend("hdfs://namenode:8020/flink/checkpoints"));
// 开启增量Checkpoint(减少Checkpoint时间)
env.getCheckpointConfig().setIncrementalCheckpointing(true);
// 设置Checkpoint间隔(10秒)
env.enableCheckpointing(10000);
// 设置Checkpoint模式(EXACTLY_ONCE)
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
4.2.3 窗口计算优化
// 使用事件时间(Event Time)处理延迟事件
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
// 提取事件时间戳(假设JSON中的"ts"字段为事件时间)
DataStream<Order> orderStream = env.addSource(consumer)
.map(json -> {
JSONObject obj = new JSONObject(json);
return new Order(
obj.getString("order_id"),
obj.getDouble("amount"),
obj.getLong("ts") // 事件时间戳(毫秒)
);
})
.assignTimestampsAndWatermarks(
WatermarkStrategy.<Order>forBoundedOutOfOrderness(Duration.ofSeconds(10)) // 允许10秒延迟
.withTimestampAssigner((order, timestamp) -> order.getTs())
);
// 滚动窗口计算(5秒)
DataStream<Double> totalSalesStream = orderStream
.keyBy(Order::getUserId) // 按用户分组
.window(TumblingEventTimeWindows.of(Time.seconds(5))) // 事件时间窗口
.sum("amount"); // 增量聚合(sum)
4.3 边缘情况处理:容错与稳定性
4.3.1 Kafka Partition Leader宕机
问题:Kafka的Partition Leader宕机后,消费者无法拉取消息;解决:Kafka的副本机制会自动选举新的Leader(由ZooKeeper或KRaft管理),Flink消费者会自动连接新的Leader,继续拉取消息。
4.3.2 Flink Checkpoint失败
问题:Checkpoint超时(如磁盘IO慢)导致作业失败;解决:
增加Checkpoint超时时间(默认60秒):;配置自动重启策略(固定延迟重启):
env.getCheckpointConfig().setCheckpointTimeout(120000);(重试3次,每次延迟10秒)。
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, 10000));
4.3.3 延迟事件处理
问题:事件时间远晚于处理时间(如延迟1小时),窗口计算结果不准确;解决:
设置允许延迟时间():
allowedLateness(窗口关闭后继续接收10分钟内的延迟事件);使用侧输出(Side Output)将延迟事件发送到单独的流,进行后续处理:
windowedStream.allowedLateness(Time.minutes(10));
OutputTag<Order> lateTag = new OutputTag<Order>("late-events") {};
SingleOutputStreamOperator<Double> resultStream = windowedStream
.sideOutputLateData(lateTag)
.sum("amount");
DataStream<Order> lateStream = resultStream.getSideOutput(lateTag);
4.4 性能考量:资源与吞吐量的平衡
4.4.1 Kafka集群性能优化
Partition数量:每个Broker的Partition数量不超过1000(避免ZooKeeper负担过重);副本数量:设置为2-3(副本越多,高可用越好,但写入性能越低);磁盘选择:使用SSD(固态硬盘),提高读写速度(比HDD快5-10倍);内存设置:Broker的JVM堆内存设置为4-8G(),避免GC频繁。
heap.size=8G
4.4.2 Flink集群性能优化
并行度设置:Flink作业的并行度应等于或大于Kafka Topic的Partition数量(如有5个Partition,并行度设为5);TaskManager资源:每个TaskManager分配2核CPU、8G内存(
order-topic),其中堆外内存设置为4G(
taskmanager.memory.process.size=8G),用于RocksDB状态存储;部署模式:生产环境使用YARN或K8s部署(支持动态资源分配),避免Standalone模式的资源浪费。
taskmanager.memory.off-heap.size=4G
5. 实际应用:从需求到落地的全流程
5.1 需求分析:明确业务目标
以金融实时风控为例,需求如下:
数据源:用户交易日志(Kafka的);处理逻辑:实时检测欺诈交易(如同一用户1分钟内多次大额转账);输出需求:将欺诈交易标记为
transaction-topic,写入Redis的
risk键;性能要求:延迟≤500毫秒,吞吐量≥10万条/秒。
risk-transactions
5.2 技术选型:匹配需求的工具链
| 层 | 工具 | 原因 |
|---|---|---|
| 数据采集层 | Fluentd | 采集交易日志,支持Kafka输出 |
| 数据传输层 | Kafka | 高吞吐、低延迟,支持Exactly-Once |
| 数据计算层 | Flink | 支持事件时间窗口、状态管理,实现欺诈检测逻辑 |
| 数据存储层 | Redis | 高并发读写,用于存储欺诈交易标记 |
| 数据服务层 | Grafana + Spring Boot | Grafana实时展示欺诈交易数量,Spring Boot提供API供风控系统调用 |
5.3 集群搭建:步骤与配置
5.3.1 Kafka集群搭建(3个Broker)
下载安装:从Apache Kafka官网下载最新版本(如3.5.0),解压到3台服务器;配置Broker:修改:
server.properties
broker.id=0 # 每个Broker的唯一ID(0、1、2)
listeners=PLAINTEXT://kafka0:9092 # 内部监听地址
advertised.listeners=PLAINTEXT://kafka0:9092 # 对外暴露地址
log.dirs=/data/kafka/logs # 日志存储目录
zookeeper.connect=zookeeper0:2181,zookeeper1:2181,zookeeper2:2181 # ZooKeeper地址
num.partitions=5 # 默认Partition数量
replication-factor=2 # 默认副本数量
启动Broker:。
bin/kafka-server-start.sh config/server.properties
5.3.2 Flink集群搭建(YARN模式)
下载安装:从Apache Flink官网下载最新版本(如1.18.0),解压到YARN集群的主节点;配置YARN:修改:
flink-conf.yaml
jobmanager.rpc.address: yarn-jobmanager # JobManager地址
taskmanager.numberOfTaskSlots: 2 # 每个TaskManager的Slot数量
state.backend: rocksdb # 状态后端(RocksDB)
state.checkpoints.dir: hdfs://namenode:8020/flink/checkpoints # Checkpoint存储目录
启动Flink集群:(启动3个TaskManager,每个2个Slot)。
bin/yarn-session.sh -n 3 -s 2
5.4 作业开发:欺诈检测逻辑实现
public class FraudDetectionJob {
public static void main(String[] args) throws Exception {
// 设置执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
env.enableCheckpointing(10000);
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
// Kafka配置
Properties kafkaProps = new Properties();
kafkaProps.setProperty("bootstrap.servers", "kafka0:9092,kafka1:9092,kafka2:9092");
kafkaProps.setProperty("group.id", "fraud-detection-group");
kafkaProps.setProperty("auto.offset.reset", "earliest");
kafkaProps.setProperty("enable.auto.commit", "false");
// 创建Kafka消费者
FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>(
"transaction-topic",
new SimpleStringSchema(),
kafkaProps
);
consumer.setCommitOffsetsOnCheckpoints(true);
// 读取交易数据,解析为Transaction对象
DataStream<Transaction> transactionStream = env.addSource(consumer)
.map(json -> {
JSONObject obj = new JSONObject(json);
return new Transaction(
obj.getString("user_id"),
obj.getDouble("amount"),
obj.getLong("ts")
);
})
.assignTimestampsAndWatermarks(
WatermarkStrategy.<Transaction>forBoundedOutOfOrderness(Duration.ofSeconds(5))
.withTimestampAssigner((tx, timestamp) -> tx.getTs())
);
// 欺诈检测逻辑:同一用户1分钟内多次大额转账(≥1000元)
DataStream<Transaction> fraudStream = transactionStream
.keyBy(Transaction::getUserId)
.window(SlidingEventTimeWindows.of(Time.minutes(1), Time.seconds(30))) // 1分钟窗口,滑动30秒
.process(new FraudDetectionProcessFunction());
// 将欺诈交易写入Redis
fraudStream.addSink(new RedisSink<>(
new RedisConfig.Builder().setHost("redis0").setPort(6379).build(),
new RedisMapper<Transaction>() {
@Override
public RedisCommandDescription getCommandDescription() {
return new RedisCommandDescription(RedisCommand.SADD, "risk-transactions");
}
@Override
public String getKeyFromData(Transaction tx) {
return "risk-transactions";
}
@Override
public String getValueFromData(Transaction tx) {
return tx.getUserId() + ":" + tx.getAmount();
}
}
));
// 执行作业
env.execute("Fraud Detection Job");
}
// 自定义ProcessFunction,实现欺诈检测逻辑
public static class FraudDetectionProcessFunction extends ProcessWindowFunction<Transaction, Transaction, String, TimeWindow> {
@Override
public void process(String userId, Context ctx, Iterable<Transaction> transactions, Collector<Transaction> out) {
int count = 0;
for (Transaction tx : transactions) {
if (tx.getAmount() ≥ 1000) {
count++;
}
}
// 同一用户1分钟内有≥2次大额转账,标记为欺诈
if (count ≥ 2) {
for (Transaction tx : transactions) {
out.collect(tx);
}
}
}
}
}
5.5 作业提交与监控
提交作业:将作业打包成JAR文件,通过Flink Web UI()提交,设置并行度为5(与
http://yarn-jobmanager:8081的Partition数量一致);监控作业:使用Grafana监控Flink作业的吞吐量(Transactions/Second)、延迟(End-to-End Latency)、Checkpoint成功率(Checkpoint Success Rate);报警设置:当Checkpoint失败次数超过3次或延迟超过500毫秒时,通过Alertmanager发送邮件报警。
transaction-topic
6. 高级考量:未来与风险
6.1 扩展动态:云原生与实时机器学习
6.1.1 云原生演进
Kafka on K8s:使用Strimzi(Kafka的K8s运算符)部署Kafka集群,支持动态扩展Broker数量;Flink on K8s:使用Flink的K8s Operator部署作业,支持弹性资源分配(根据数据量自动调整TaskManager数量)。
6.1.2 实时机器学习
实时特征工程:用Flink从Kafka的中提取用户特征(如最近1小时的点击次数),写入Redis;实时模型推理:用TensorFlow Serving加载机器学习模型(如欺诈检测模型),从Redis读取特征,实时预测交易风险;实时模型更新:用Flink消费模型更新Topic(如
user-behavior-topic),动态更新TensorFlow Serving的模型。
model-update-topic
6.2 安全影响:数据隐私与权限控制
6.2.1 Kafka的安全配置
ACL(访问控制列表):限制用户对Topic的访问权限(如);SSL/TLS加密:加密生产者与消费者之间的通信(修改
allow user alice to write on topic order-topic中的
server.properties);SASL认证:使用SASL/PLAIN认证(修改
ssl.enabled.protocols=TLSv1.2中的
server.properties)。
sasl.enabled.mechanisms=PLAIN
6.2.2 Flink的安全配置
Kerberos认证:配置Flink与Hadoop生态组件(如HDFS、YARN)之间的Kerberos认证(修改中的
flink-conf.yaml);SSL/TLS加密:加密Flink Web UI的通信(修改
security.kerberos.login.keytab中的
flink-conf.yaml)。
rest.ssl.enabled=true
6.3 伦理维度:公平与透明
数据公平性:实时推荐系统应避免偏见(如推荐结果偏向高消费用户),可通过重新采样(Resampling)或对抗训练(Adversarial Training)优化算法;数据透明度:用户应知道他们的数据被如何处理(如实时风控系统使用了哪些交易数据),可通过隐私政策或数据使用说明向用户披露。
6.4 未来演化向量
多模态数据处理:支持文本、图像、音频等多模态数据的实时处理(如实时视频监控中的物体检测);低代码/无代码开发:使用Flink SQL Client或Kafka KSQL开发实时作业(如);边缘计算:将Flink与Kafka部署在边缘节点(如物联网设备),实现低延迟的实时处理(如工业设备的实时监控)。
SELECT user_id, sum(amount) FROM order-topic GROUP BY TUMBLE(ts, INTERVAL '5' SECOND)
7. 综合与拓展:从知识到实践的升华
7.1 跨领域应用案例
电商:实时订单分析、实时库存更新、实时推荐系统;金融:实时风控、实时交易分析、实时账户余额更新;物流:实时货物跟踪、实时路线优化、实时配送预测;医疗:实时病人监测、实时医疗数据分析、实时诊断建议。
7.2 研究前沿:待解决的问题
超高吞吐量处理:如何处理每秒1000万条消息的实时数据流?(需优化Kafka的Partition模型与Flink的算子链);延迟事件处理:如何处理事件时间比处理时间晚几个小时的事件?(需引入迟到事件存储,如Apache Hudi);跨集群容错:如何实现Kafka集群与Flink集群分布在不同区域的容错?(需使用多区域复制,如Kafka的MirrorMaker 2)。
7.3 战略建议:企业落地指南
需求驱动:避免过度设计,根据业务需求选择技术栈(如小流量场景可使用Flink Standalone模式);架构可扩展:设计时考虑未来数据量的增长(如Kafka的Partition数量可动态增加);监控与运维:建立完善的监控体系(如Prometheus+Grafana),及时发现和解决问题;技术迭代:及时升级Kafka与Flink的版本(如Kafka 3.0的KRaft模式、Flink 1.18的K8s支持),享受新功能与优化。
结论:Flink+Kafka是实时数据架构的黄金组合
Flink与Kafka的协同,完美解决了实时数据架构的高效传输与精准计算问题,成为企业实现实时决策的核心支撑。通过本文的原理解析、实践指南与调优攻略,读者可以系统掌握Flink+Kafka的构建方法,并将其应用于实际业务场景。未来,随着云原生、实时机器学习等技术的发展,Flink+Kafka的组合将继续演化,支持更多的实时智能场景。
参考资料
Apache Kafka官方文档:https://kafka.apache.org/documentation/Apache Flink官方文档:https://flink.apache.org/documentation/《Kafka权威指南》(作者:Neha Narkhede等)《Flink实战》(作者:董西成)《实时流处理:Flink原理与实践》(作者:阿里巴巴实时计算团队)Apache Flink 1.18 Release Notes:https://flink.apache.org/news/2023/11/28/release-1.18.0.htmlApache Kafka 3.5 Release Notes:https://kafka.apache.org/35/documentation.html#release_notes_3_5_0





