为什么要学习Flink

35 阅读6分钟

大家好,我是炫。欢迎来到我的 Flink 专栏,一个专注于协助你深入学习 Flink 技术的地方。

我最早从 Flink 的 Release 版本开始关注,可谓是国内最早一批深入研究 Flink 的开发者之一。在 Flink 的基础上,我成功开发了实时计算业务应用、实时数据仓库以及监控报警系统,积累了丰富的生产实践经验。

面试是每位开发者都必须面对的一道坎

在工作中,由于项目需要,我进行过多次 Flink 开发工程师的面试。在这个过程中,我发现一些普遍存在的问题,例如:

  • 对 Flink 核心概念和原理的掌握不够扎实,导致在实际业务中难以游刃有余,甚至在面试中被淘汰;
  • 那些能通过简历筛选的人通常具有实时流计算开发的经验,能够应对典型场景下的问题,但在面对非典型但常见的业务场景问题时表现得支支吾吾;
  • 有些面试者声称参与了实时计算平台的架构设计、开发、发布和运维等全流程工作,但细究起来发现其实参与度很低,只是团队中的一个“小透明”;
  • 有人能够熟练回答在项目中如何应用 Flink,但对于底层源码级别的实现却一无所知。

这些问题看似各异,但实质上都是在全方位考察你对技术原理的理解深度以及在实际工作中解决问题的能力。

想要进入大厂?掌握 Flink 技术势在必行

随着大数据时代的发展和海量数据的实时处理需求激增,传统的批处理方式和早期的流式处理框架逐渐显露出局限性。在这个背景下,Flink 凭借其独特的流式计算特性和先进的架构设计,显著改善了以前流式处理框架的问题。

越来越多的国内公司开始采用 Flink 进行实时数据处理。阿里巴巴率先在全集团推广 Flink 技术,例如 Flink SQL 与 Hive 生态的集成、拥抱 AI 等;腾讯、百度、字节跳动、滴滴、华为等众多互联网公司也将 Flink 视为未来技术的重要发展方向。在未来的 3 ~ 5 年内,Flink 必将成为企业内部主流的数据处理框架,也是进入大厂的“敲门砖”。

你的困扰,我来解答

回首往事,我在学习 Flink 的过程中也曾遇到许多困扰。有时可能是因为官方文档理解不到位,有时可能是对底层原理认知不足,有时可能是在项目中遇到的问题难以找到解决方案。我能理解你的困扰,因为我也曾经历过同样的阶段。

在 Flink 学习过程中,我面临了许多挑战。一开始并没有中文文档,例如在处理消息乱序问题和应对 Flink 复杂的窗口设计和水印生成时,我不得不在晦涩的英文文档、社区邮件列表和源码中寻找答案。

目前市面上的 Flink 资源仍然较为有限,而且由于 Flink 更新迭代较快、文档更新不及时,我们在学习和实践中仍然面临诸多难点和各种问题:

  • 当开发者面对新增 API 时,官网找不到答案;
  • Flink 的一些概念难以理解,文档全部是英文的,进一步增加了理解难度;
  • Flink 在生产实践中会遇到大量的问题,任何参数和 API 的不正确使用都会导致灾难性后果,比如数据倾斜、反压、多流 join 等,但这正是我们学习进阶和面试大厂必须掌握的。

因此,真正掌握生产环境下的问题处理技能,才能称得上是掌握了 Flink。在 Flink 实践应用中,由于 Flink 社区发展时间较短,版本迭代频繁,很多开发者不得不在摸索中前进,出现问题没有可以借鉴的经验,使得开发者束手无策。因此,我在设计专栏时,将 Flink 相关的基础理论与实战案例相结合,基于 Flink 最新的版本,从基础概念入手,通过大量的实战代码演练,带你进入真实的生产环境,学习如何解决当下企业内部真实面临的生产实践问题,获得大厂一线生产实践的宝贵经验。

我希望能够帮

助那些渴望深入学习 Flink 技术、提升 Flink 应用水平的开发者们。无论你是准备面试大厂的 Flink 岗位,还是希望在实际工作中应用 Flink 解决实际问题,亦或是对 Flink 感兴趣想要深入了解的人,我都会为你提供一系列实用且高质量的教程和文章,助你快速掌握 Flink 的核心技术。希望通过专栏的内容,你能够更好地理解 Flink,掌握 Flink 的实际应用技能,提高在实际工作中解决问题的能力,最终能够在面试和实际工作中游刃有余,成为业界一流的 Flink 开发工程师。

package org.myorg.quickstart.DataStreamAPI04;


import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import java.util.ArrayList;
import java.util.List;

/**
 *这段代码演示了在Flink中使用keyBy和reduce操作。它接受一个元组流,按第一个字段为它们设置键,然后通过对每个键组中的第三个字段求和来进行缩减。结果被打印到标准错误流。
 * 
 * > 生产环境无界流不建议使用聚合函数,那一些聚合的需求,应该怎么处理?
 *
 *  讲师回复:不建议的是那些状态无限增长的聚合,实际应用中一般会配合窗口使用。使得状态不会无限制扩张
 */
class StreamingDemo2 {

    public static void main(String[] args) throws Exception {

        // 设置Flink执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 定义输入数据
        List<Tuple3<Integer, Integer, Integer>> data = new ArrayList<>();
        data.add(new Tuple3<>(0, 1, 0));
        data.add(new Tuple3<>(0, 1, 1));
        data.add(new Tuple3<>(0, 2, 2));
        data.add(new Tuple3<>(0, 1, 3));
        data.add(new Tuple3<>(1, 2, 5));
        data.add(new Tuple3<>(1, 2, 9));
        data.add(new Tuple3<>(1, 2, 11));
        data.add(new Tuple3<>(1, 2, 13));
        data.add(new Tuple3<>(1, 2, 40));

        // 从输入数据创建数据流
        DataStreamSource<Tuple3<Integer, Integer, Integer>> items = env.fromCollection(data);


        // 根据元组的第一个字段进行分组,并通过减少操作对第三个字段求和
        SingleOutputStreamOperator<Tuple3<Integer, Integer, Integer>> reduce = items.keyBy(0).reduce(new ReduceFunction<Tuple3<Integer, Integer, Integer>>() {
            @Override
            public Tuple3<Integer, Integer, Integer> reduce(Tuple3<Integer, Integer, Integer> t1, Tuple3<Integer, Integer, Integer> t2) throws Exception {
                // 创建一个新的元组,具有相同的键(字段0)和第三个字段(字段2)的总和
                Tuple3<Integer, Integer, Integer> newTuple = new Tuple3<>();
                newTuple.setFields(1, 0, (Integer) t1.getField(2) + (Integer) t2.getField(2));
                return newTuple;
            }
        });

        // 将结果打印到标准错误流
        reduce.printToErr().setParallelism(1);

        // 执行Flink作业
        String jobName = "user defined streaming source";
        env.execute(jobName);
    }

}