一、为什么需要Flink?

当你在电商平台秒杀商品时,1毫秒的延迟可能导致交易失败;当自动驾驶汽车遇到障碍物时,10毫秒的计算延迟可能酿成事故。这些场景揭示了一个残酷事实:数据的价值随时间呈指数级衰减。

传统批处理(如Hadoop)像老式火车,必须等所有乘客(数据)到齐才能发车;而流处理(如Flink)如同磁悬浮列车,每个乘客(数据)上车即刻出发。Flink的诞生,让数据从"考古材料"变为"新鲜血液"。

二、初识Flink

1. 定义

Apache Flink是由德国柏林工业大学于2009年启动的研究项目,2014年进入Apache孵化器,现已成为实时计算领域的事实标准。其核心能力可用一句话概括:对无界和有界数据流进行有状态计算。

2. 核心特性

流处理优先:批处理是流处理的特例(有界数据流)

事件时间语义:按数据真实发生时间处理(而非系统接收时间)

精确一次语义:确保计算结果100%准确

亚秒级延迟:处理延迟可控制在毫秒级

3. 技术架构

Flink运行时架构包含三个关键角色:

  • JobManager:大脑中枢,负责任务调度与检查点管理
  • TaskManager:肌肉组织,执行具体计算任务
  • Dispatcher:网关系统,提供REST接口提交作业

三、环境搭建

环境要求

​1. ​Windows 10 2004 或更高版本​​(建议使用 Windows 11)

​2. ​已启用 WSL 2​​

3. 存储空间:至少 1GB 可用空间

详细安装步骤

步骤 1:启用 WSL

在 PowerShell 中以管理员身份运行以下命令:


# 启用 WSL 功能
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart # 启用虚拟机平台
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart # 设置 WSL 2 为默认版本
wsl --set-default-version 2 # 重启电脑(必须步骤)

步骤 2:安装 Ubuntu

​1. 打开 Microsoft Store

​2. 搜索安装 ​​Ubuntu 22.04 LTS​​

3. 启动 Ubuntu 并创建用户名和密码

步骤 3:安装 Java 17

在 Ubuntu 终端执行:

  # 更新软件包列表
sudo apt update # 安装 Java 17
sudo apt install -y openjdk-17-jdk
# 设置环境变量
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' >> /etc/profile
echo 'export PATH=$PATH:$JAVA_HOME/bin' >> /etc/profile
source /etc/profile
# 验证安装
java -version
# 应显示类似:OpenJDK Runtime Environment (build 17.0.14+...)

步骤 4:下载并安装 Flink 1.20.1

  # 下载 Flink
wget https://archive.apache.org/dist/flink/flink-1.20.1/flink-1.20.1-bin-scala_2.12.tgz # 解压安装包
tar xzf flink-1.20.1-bin-scala_2.12.tgz # 移动到安装目录
sudo mv flink-1.20.1 /opt/flink # 设置环境变量 echo 'export FLINK_HOME=/opt/flink' >> /etc/profile
echo 'export PATH=$PATH:$FLINK_HOME/bin' >> /etc/profile
source /etc/profile

步骤 5:修改内存配置

编辑配置文件:

vi /opt/flink/conf/conf.yaml

修改以下关键参数:

  jobmanager:
bind-host: 0.0.0.0
rpc:
address: localhost
port: 6123
memory:
process:
size: 1600m
execution:
failover-strategy: region taskmanager:
bind-host: 0.0.0.0
host: localhost
numberOfTaskSlots: 2
memory:
process:
size: 2048m
parallelism:
default: 2 rest:
address: localhost
bind-address: 0.0.0.0
port: 8081

步骤 6:启动 Flink 集群


# 启动集群(JobManager + TaskManager)
$FLINK_HOME/bin/start-cluster.sh # 检查运行状态
jps

步骤 7:访问 Web UI

在 Windows 浏览器中访问:

http://localhost:8081

四、实战第一个Flink程序:BatchWordCount

下面将详细介绍如何在Flink环境中创建并运行第一个WordCount程序。这个经典示例将带你从项目创建到代码执行,全面体验Flink开发流程。

项目结构设计

采用多模块Gradle项目,结构清晰:

  flink-learning/
├── build.gradle # 根项目构建配置
├── settings.gradle # 多模块配置
├── libraries.gradle # 依赖统一管理
├── data/ # 数据文件夹
│ ├── input.txt # 输入文件
│ └── output.txt # 输出文件
└── wordcount/ # WordCount模块
├── build.gradle # 模块构建配置
└── src/main/java # 源代码目录
└── cn/com/daimajiangxin/flink/wordcount
└── BatchWordCount.java # 主程序

核心文件配置

详细配置参考代码仓库:https://gitee.com/daimajiangxin/flink-learning.git

WordCount代码实现

package cn.com.daimajiangxin.flink.wordcount;

import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.connector.file.src.FileSource;
import org.apache.flink.connector.file.src.reader.TextLineFormat;
import org.apache.flink.core.fs.Path;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector; import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Arrays; public class BatchWordCount { public static void main(String[] args) throws Exception {
// 转换Windows路径格式
args = convertWindowsPaths(args); // 参数校验
if (args.length < 2) {
System.err.println("Usage: BatchWordCount <input> <output> [--parallelism=N]");
System.err.println("Example: BatchWordCount input.txt output.txt --parallelism=4");
System.exit(1);
} final String inputPath = args[0];
final String outputPath = args[1];
int parallelism = 1; // 默认并行度 // 1. 创建流批一体执行环境
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 明确指定批处理模式
env.setRuntimeMode(RuntimeExecutionMode.BATCH); // 设置并行度和作业名称
env.setParallelism(parallelism);
env.getConfig().enableObjectReuse(); // 2. 使用最新的FileSource API读取输入数据
DataStream<String> text = createFileSource(env, inputPath, parallelism); // 3. 定义处理逻辑
SingleOutputStreamOperator<Tuple2<String, Integer>> counts = text
.flatMap(new Tokenizer())
.name("Tokenizer")
.setParallelism(parallelism)
.keyBy(value -> value.f0)
.reduce(new SumReducer())
.name("SumReducer")
.setParallelism(parallelism)
.returns(TypeInformation.of(new TypeHint<Tuple2<String, Integer>>() {})); // 4. 输出结果到文件
counts.writeAsText(outputPath)
.name("FileSink")
.setParallelism(1); // 5. 执行作业
try {
System.out.println("Starting Flink WordCount job...");
System.out.println("Input path: " + inputPath);
System.out.println("Output path: " + outputPath);
System.out.println("Parallelism: " + parallelism); env.execute("Flink Batch WordCount Example");
System.out.println("Job completed successfully!"); } catch (Exception e) {
System.err.println("Job execution failed: " + e.getMessage());
e.printStackTrace();
}
} // Windows路径转换
private static String[] convertWindowsPaths(String[] args) {
if (args.length >= 1) {
args[0] = "file:///" + args[0]
.replace("\\", "/")
.replace(" ", "%20");
}
if (args.length >= 2) {
args[1] = "file:///" + args[1]
.replace("\\", "/")
.replace(" ", "%20");
}
return args;
} // 创建文件源
private static DataStream<String> createFileSource(
StreamExecutionEnvironment env,
String path,
int parallelism) {
// 使用file://前缀
Path filePath = new Path(path); System.out.println("Loading file from: " + filePath); TextLineFormat format = new TextLineFormat(StandardCharsets.UTF_8); FileSource<String> fileSource = FileSource
.forRecordStreamFormat(format, filePath)
.build(); WatermarkStrategy<String> watermarkStrategy = WatermarkStrategy
.<String>forMonotonousTimestamps()
.withIdleness(Duration.ofSeconds(10)); return env.fromSource(
fileSource,
watermarkStrategy,
"FileSource"
)
.name("FileSource")
.setParallelism(1);
} // 分词器
public static final class Tokenizer implements FlatMapFunction<String, Tuple2<String, Integer>> {
@Override
public void flatMap(String value, Collector<Tuple2<String, Integer>> out) {
// 过滤空行
if (value == null || value.trim().isEmpty()) return; // 转换为小写并分割单词
String[] words = value.toLowerCase().split("\\W+"); for (String word : words) {
if (!word.isEmpty()) {
out.collect(Tuple2.of(word, 1));
}
}
}
} // 累加器
public static final class SumReducer implements ReduceFunction<Tuple2<String, Integer>> {
@Override
public Tuple2<String, Integer> reduce(Tuple2<String, Integer> v1, Tuple2<String, Integer> v2) {
return Tuple2.of(v1.f0, v1.f1 + v2.f1);
}
}
}

输入文件示例 (input.txt)

input.txt参考代码仓库:https://gitee.com/daimajiangxin/flink-learning.git

运行Flink作业

这里讲述在IDEA中运行刚刚写的BatchWordCount 任务,配置IDEA的APPlication。

VM选项配置

  --add-exports=java.base/sun.net.util=ALL-UNNAMED
--add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.net=ALL-UNNAMED
--add-opens=java.base/java.io=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED
--add-opens=java.base/java.text=ALL-UNNAMED
--add-opens=java.base/java.time=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent.locks=ALL-UNNAMED

程序参数

 代码放置路径\\flink-learning\\data\\input.txt
代码放置路径\bigdata\\flink-learning\\data\\output.txt

运行BatchWordCount类

Run 或者Debug BatchWordCount的 APPlication.

预期输出

运行成功data目录下会生成output的文件。

(processing,1)
(batch,2)
(flink,2)
(hello,2)

五、技术要点解析

  • 流批一体API:Flink 1.20+使用StreamExecutionEnvironment统一处理批流
  • 文件源:使用FileSource API
  • 精确一次处理:批处理天然支持Exactly-Once语义
  • 并行度控制:通过setParallelism控制任务并行度
  • Windows路径适配:统一转换为file:///开头的URI格式

六、学习路线建议

完成WordCount后,可逐步探索:

  • 实时流处理(SocketWordCount)
  • 状态管理(StatefulProcessing)
  • 事件时间处理(EventTimeProcessing)
  • 窗口计算(TumblingWindow、SlidingWindow)
  • CEP复杂事件处理
  • Table API和SQL

    通过这个完整的BatchWordCount实例,你已经掌握了Flink项目的搭建、编码和运行全流程。随着Flink在实时数据处理领域的广泛应用,这些技能将成为大数据开发的宝贵资产。

源文来自:http://blog.daimajiangxin.com.cn

源码地址:https://gitee.com/daimajiangxin/flink-learning

从零开始学Flink:揭开实时计算的神秘面纱的更多相关文章

  1. (二)基于商品属性的相似商品推荐算法——Flink SQL实时计算实现商品的隐式评分

    系列随笔: (总览)基于商品属性的相似商品推荐算法 (一)基于商品属性的相似商品推荐算法--整体框架及处理流程 (二)基于商品属性的相似商品推荐算法--Flink SQL实时计算实现商品的隐式评分 ( ...

  2. 揭开webRTC媒体服务器的神秘面纱——WebRTC媒体服务器&开源项目介绍

    揭开webRTC媒体服务器的神秘面纱--WebRTC媒体服务器&开源项目介绍 WebRTC生态系统是非常庞大的.当我第一次尝试理解WebRTC时,网络资源之多让人难以置信.本文针对webRTC ...

  3. 揭开A*算法的神秘面纱

    揭开A*算法的神秘面纱 一.总结 一句话总结:f(n)=g(n)+h(n) 这个算法有点像BFS的优化算法. g(n)为起点到当前方格的距离,这个是已知的. h(n)为当前方格到终点的距离,这个简单点 ...

  4. 【转】再讲IQueryable<T>,揭开表达式树的神秘面纱

    [转]再讲IQueryable<T>,揭开表达式树的神秘面纱 接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个 ...

  5. 1.揭开消息中间件RabbitMQ的神秘面纱

    当你看到这篇博文的时候,相信你至少已经知道RabbitMQ 是一个非常优秀的消息中间件,它使用专门处理高并发的Erlang 语言编写而成的消息中间件产品. 当然如果你不知道也没关系,读完本篇你将Get ...

  6. 揭开HTTP网络协议神秘面纱系列(三)

    HTTP首部字段有四种类型:通用首部字段,请求首部字段,响应首部字段,实体首部字段. 通用首部字段: 首部字段 说明 Cache-Control 控制缓存的行为 Connection 逐跳首部.连接的 ...

  7. 揭开yield关键字的神秘面纱

    写在前言 经常会看见,python函数中带有yield关键字,那么yield是什么,有什么作用? 答案:可以理解yield是一个生成器: 作用:遇到yield关键字,函数会直接返回yield值,相当于 ...

  8. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  9. 揭开SQL注入的神秘面纱PPT分享

        SQL注入是一个老生常谈但又经常会出现的问题.该课程是我在公司内部培训的课程,现在分享出来,希望对大家有帮助.     点击这里下载.

  10. 揭开HTTP网络协议神秘面纱系列(二)

    HTTP报文内的HTTP信息 HTTP协议交互的信息被称为HTTP报文,请求端的HTTP报文叫做请求报文,响应端的叫做响应报文. HTTP为了提升传输速率,其在传输数据时,按照数据原样进行压缩传输,相 ...

随机推荐

  1. Ubuntu 卸载安装nginx

    nginx很顽强,单独的删除它的文件是不够的,这会导致你再次安装时出现一系列的问题. 1.卸载nginx,及其配置文件 sudo apt-get --purge remove nginx 2.自动全部 ...

  2. 基于OpenSSL的密码管理系统-应用密码学课程报告

    第1章 概要设计 1.1 设计目的 本研究旨在设计并实现一个基于OpenSSL的密码管理系统,该系统具备密钥对的生成.密钥上传.密钥的核对.身份认证.文件与邮件的加密和解密.数字签名及数字证书管理等常 ...

  3. chrome播放webRTC的H265视频方法

    需求描述 最近有需求实现浏览器直接播放摄像头视频 鉴于Camera本身支持了rtsp流,本想web直接播放rtsp,但是还不行,搜了一下webRTC实现的效果和延迟会好一些.于是就使用了mediaMT ...

  4. 探秘Transformer系列之(15)--- 采样和输出

    探秘Transformer系列之(15)--- 采样和输出 目录 探秘Transformer系列之(15)--- 采样和输出 0x00 概述 0x01 Generator 1.1 Linear 1.2 ...

  5. 国内四大骨干网与十大ISP服务商

    1.骨干网 几台计算机连接起来,互相可以看到其他人的文件,这叫局域网,整个城市的计算机都连接起来,就是城域网,把城市之间连接起来的网就叫骨干网.这些骨干网是国家批准的可以直接和国外连接的互联网.其他有 ...

  6. Devops工程师需要具备的10项技能

    Facebook.Amazon和Microsoft等公司正在大量使用DevOps技术来确保软件的一致交付,DevOps的的工作机会和所需要的技能集也是越来越多. 在这里,我们将讨论Devops工程师需 ...

  7. JVM 的组成

    JVM 的组成 JVM(Java Virtual Machine)是 Java 的核心组件,负责执行 Java 字节码程序.以下是 JVM 的主要组成部分: 1. 类加载子系统(Class Loade ...

  8. centos停服,迁移centos7.3系统到新搭建的openEuler

    背景 最近在做的事,简单来讲,就是一套系统差不多有10多台虚拟机,都是centos系统,版本主要是7.3.7.6.7.9,现在centos停止维护了,转为了centos stream,而centos ...

  9. Mysql数据库常用操作和Mysql大数据高效迁移方案

    1.数据迁移: 1.数据量较少时可使用mysqldump和mysql命令导出和导入 # 导出指定数据库系统 mysqldump -u _username -p _dbname > _sqlfil ...

  10. .net core日志NLog的使用

    Nlog日志使用 视频:https://www.bilibili.com/video/BV1bv4y1a79X 参照:https://www.cnblogs.com/sheng-jie/p/17169 ...