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 作为流水线的核心,不仅对数据进行有效处理,还确保了高效、实时地传递和存储处理结果。

相关推荐
angen20181 小时前
kafka + flink +mysql 案例
flink·kafka
神秘打工猴1 小时前
数据仓库为什么要分层
大数据·数据仓库·spark
Hard_pea1 小时前
Spark 深入解析
大数据·分布式·spark
闯闯桑2 小时前
Scala 中的访问修饰符
大数据·开发语言·scala
后端小肥肠2 小时前
解锁DeepSpeek-R1大模型微调:从训练到部署,打造定制化AI会话系统
大数据·人工智能
24k小善10 小时前
flink集成tidb cdc
大数据·flink·tidb
kngines12 小时前
【实战ES】实战 Elasticsearch:快速上手与深度实践-3.2.3 案例:新闻搜索引擎的相关性优化
大数据·elasticsearch·搜索引擎
秦南北13 小时前
国内领先的宠物类电商代运营公司品融电商
大数据·人工智能·电商
problc15 小时前
Manus AI 全球首款通用型 Agent,中国制造
大数据·人工智能·制造
*星星之火*18 小时前
【Flink银行反欺诈系统设计方案】3.欺诈的7种场景和架构方案、核心表设计
大数据·架构·flink