Flink随笔 20241129 流数据处理:以生产线烤鸡为例理解 Flink

流数据(streaming data)就像是一条永不停歇的生产线,源源不断地向前推进,带来新的数据。而 Apache Flink 就是这条生产线的核心,它负责对数据进行处理、分类、聚合和存储。为了更好地理解 Flink 的流处理,我们可以通过一个简单的类比来解释:流数据就像是流水线上的烤鸡,而 Flink 就是这条流水线上的工作部,负责对这些烤鸡进行加工、分拣、统计和存储。

下面,我们将通过这个类比一步步讲解 Flink 的核心概念,并展示如何在 Flink 中实现这些操作。

类比:生产线的烤鸡

想象一下,你在一个生产线的末端,看到源源不断的烤鸡从流水线上流过。你需要对这些鸡进行以下操作:

  1. 去掉烤糊的鸡肉(过滤):生产线上有些鸡被烤得过焦,不能食用,需要将其剔除。
  2. 分拣出火鸡还是普通鸡肉(映射):在生产线的下一步,你需要把鸡肉分成不同的类别,比如火鸡和普通鸡肉。
  3. 统计有多少只火鸡,多少只普通鸡肉(聚合):你需要统计每种鸡肉的数量,以便后续处理。
  4. 将鸡肉存储(存储):最后,所有的合格鸡肉需要被存储,或者被送到市场。

这些操作正是 Flink 中流数据处理的核心功能。下面我们将逐一介绍如何在 Flink 中实现这些步骤。

1. 去掉烤糊的鸡肉(过滤)

在生产线的第一步,你需要对烤鸡进行筛选,去掉那些已经烤糊或者质量不合格的鸡肉。在 Flink 中,这就是 过滤操作 (Filter)。Flink 提供了 filter() 函数,可以根据条件筛选出符合要求的数据。

例如,假设我们有一个数据流,其中包含不同类型的鸡肉,而我们只关心健康的鸡肉。你可以通过过滤操作去除那些不符合条件的数据。

java 复制代码
DataStream<String> chickenStream = env.fromElements("Turkey", "Burnt Chicken", "Chicken", "Turkey");

DataStream<String> validChickenStream = chickenStream.filter(chicken -> !chicken.equals("Burnt Chicken"));
validChickenStream.print();
2. 分拣出火鸡还是普通鸡肉(映射)

在生产线的第二步,你需要把鸡肉分成火鸡和普通鸡肉两类,这就是 映射操作 (Map)。在 Flink 中,map() 函数可以将输入数据转换成不同的输出数据。在本例中,我们可以将鸡肉类型映射成不同的标签,例如"火鸡"和"普通鸡肉"。

java 复制代码
DataStream<String> sortedChickenStream = chickenStream
    .map(new MapFunction<String, String>() {
        @Override
        public String map(String value) throws Exception {
            return value.equals("Turkey") ? "Turkey" : "Chicken";
        }
    });

sortedChickenStream.print();
3. 统计有多少只火鸡,多少只普通鸡肉(聚合)

接下来,你需要统计每种类型的鸡肉有多少只,这就是 聚合操作 (Aggregation)。在 Flink 中,keyBy()reduce() 函数常常一起使用,按指定的键(比如鸡肉类型)对数据进行分组,并对每个组进行聚合计算。

例如,你可以按鸡肉类型分组,并统计每种鸡肉的数量:

java 复制代码
DataStream<Tuple2<String, Integer>> mappedStream = chickenStream
    .map(chicken -> new Tuple2<>(chicken, 1));  // 每个鸡肉事件映射为类型和数量的元组

DataStream<Tuple2<String, Integer>> aggregatedStream = mappedStream
    .keyBy(0)  // 按鸡肉类型分组
    .reduce(new ReduceFunction<Tuple2<String, Integer>>() {
        @Override
        public Tuple2<String, Integer> reduce(Tuple2<String, Integer> value1, Tuple2<String, Integer> value2) throws Exception {
            return new Tuple2<>(value1.f0, value1.f1 + value2.f1);  // 累加数量
        }
    });

aggregatedStream.print();
4. 将鸡肉存储(存储)

在生产线的最后一步,合格的鸡肉需要被存储或发送到市场。Flink 提供了多种 Sink 操作,可以将处理结果输出到外部系统,如 Kafka、MySQL、Elasticsearch 或 HDFS。你可以根据需要将聚合结果写入数据库或消息队列,便于后续的处理和存储。

例如,将处理后的数据输出到 Kafka:

java 复制代码
aggregatedStream.addSink(new FlinkKafkaProducer<>(
    "kafka-broker",  // Kafka 服务器地址
    "chicken-topic",  // Kafka 主题
    new SimpleStringSchema()  // 数据序列化方式
));

通过上述步骤,我们可以编写一个完整的 Flink 程序,来实现流数据的处理,类似于生产线上的烤鸡加工过程。以下是一个简单的例子,展示如何使用 Flink 进行数据流的过滤、映射、聚合和存储:

java 复制代码
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.api.java.tuple.Tuple2;

public class ChickenProcessing {
    public static void main(String[] args) throws Exception {
        // 1. 设置流处理环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 2. 输入数据流:每个事件包含一个鸡肉的类型
        DataStream<String> chickenStream = env.fromElements("Turkey", "Chicken", "Turkey", "Chicken", "Turkey");

        // 3. 映射:将每个事件映射为一个元组(鸡肉类型, 数量)
        DataStream<Tuple2<String, Integer>> mappedStream = chickenStream
            .map(new MapFunction<String, Tuple2<String, Integer>>() {
                @Override
                public Tuple2<String, Integer> map(String value) throws Exception {
                    return new Tuple2<>(value, 1);  // 每个事件都标记为1个鸡肉
                }
            });

        // 4. 聚合:按类型统计每种鸡肉的数量
        DataStream<Tuple2<String, Integer>> aggregatedStream = mappedStream
            .keyBy(0)  // 按鸡肉类型分组
            .reduce(new ReduceFunction<Tuple2<String, Integer>>() {
                @Override
                public Tuple2<String, Integer> reduce(Tuple2<String, Integer> value1, Tuple2<String, Integer> value2) throws Exception {
                    return new Tuple2<>(value1.f0, value1.f1 + value2.f1);  // 累加数量
                }
            });

        // 5. 输出结果到控制台
        aggregatedStream.print();

        // 6. 启动流处理作业
        env.execute("Chicken Processing");
    }
}

输出示例

bash 复制代码
(Turkey, 3)
(Chicken, 2)
结论

通过上面的例子,我们可以看到 Flink 在流数据处理中的应用。它不仅可以对数据进行过滤、分类和聚合,还能够将处理结果存储或发送到其他系统。流数据处理就像生产线上的烤鸡加工一样,Flink 作为流水线的核心,不仅对数据进行有效处理,还确保了高效、实时地传递和存储处理结果。

相关推荐
AI智能探索者5 小时前
揭秘大数据领域特征工程的核心要点
大数据·ai
做cv的小昊6 小时前
【TJU】信息检索与分析课程笔记和练习(8)(9)发现系统和全文获取、专利与知识产权基本知识
大数据·笔记·学习·全文检索·信息检索
AC赳赳老秦6 小时前
DeepSeek 私有化部署避坑指南:敏感数据本地化处理与合规性检测详解
大数据·开发语言·数据库·人工智能·自动化·php·deepseek
C7211BA8 小时前
通义灵码和Qoder的差异
大数据·人工智能
三不原则8 小时前
银行 AIOps 实践拆解:金融级故障自愈体系如何搭建
大数据·运维
大厂技术总监下海10 小时前
数据湖加速、实时数仓、统一查询层:Apache Doris 如何成为现代数据架构的“高性能中枢”?
大数据·数据库·算法·apache
2501_9418824812 小时前
AI系统工程化架构与大模型部署实践分享
flink
新诺韦尔API12 小时前
手机三要素验证不通过的原因?
大数据·智能手机·api
成长之路51413 小时前
【数据集】分地市全社会用电量统计数据(2004-2022年)
大数据
InfiSight智睿视界13 小时前
门店智能体技术如何破解美容美发连锁的“标准执行困境”
大数据·运维·人工智能