1.1 Flink定位
出于以下两个原因,我们先来探讨Flink是什么及目前业内常见的应用场景。
❑有的人对Flink的定位不明确,如果我们连一个工具是什么都没有搞明白,那么用好这个工具就是天方夜谭了。
❑我们在工作和学习中,调研和使用大数据引擎的第一步就是了解这个引擎能帮助我们做什么事情,并参考业内其他企业使用这个引擎做过的应用,只有在明确了这个引擎是否契合我们的应用场景之后,才会继续深入调研其API的使用。
通过本节的介绍,不熟悉Flink的读者可以了解Flink的基础能力并明确其定位,熟悉Flink的读者可以去探索Flink更丰富的功能及应用场景。
1.1.1 Flink是什么
初学者对Flink的第一印象应该是一个大数据流处理引擎,其中有两个关键词。
1.大数据处理引擎
这个关键词强调Flink的定位是数据处理,我们可以使用Flink从一个数据存储引擎(比如Kafka)中读取数据、使用Flink提供的各种数据计算API来灵活处理数据、产出数据到一个新的数据存储引擎(比如MySQL)中,常见的大数据处理引擎还有Hive、Spark等。
2.大数据流(实时)处理引擎
这个关键词强调Flink目前的主要应用场景是流处理领域。想要明白什么是流(实时)处理,可以用批(离线)处理进行对比。任何数据处理作业的运行过程无非3个关键点,即输入→处理→输出。
对于批处理来说,这个运行过程对应着批输入→批处理→批输出,其中批代表着输入的数据集合是有限的,接下来在这个有限的数据集合上进行统一的处理,最后产出有限的数据集合,执行完后这个计算作业就结束了。举例来说,如图1-1所示,从一个文件中读取数据(批输入),然后对文件数据进行处理(批处理),将计算结果写到另一个文件中(批输出)。在大数据领域,批处理的典型案例就是离线数仓。
图1-1 批处理流程
而对于流处理来说,这个运行过程对应着流输入→流处理→流输出,其中流代表输入的数据集合是实时的、无限的,接下来处理输入的数据流,最后产出数据流。常见的流处理流程如图1-2所示。
图1-2 流处理流程
虽然目前Flink兼具批、流处理能力,但是Flink的批处理能力相比其突出的流处理能力来说,还有待完善,并且对于应用场景来说,业界目前主要使用Flink的流处理能力解决业务场景中的问题,因此本书主要围绕Flink的流处理能力展开。
1.1.2 Flink对于数据的定义
对于大数据处理引擎来说,框架设计理论都是围绕着数据展开的,数据是核心,因此对于数据本身的理解和定义就是设计一个大数据处理引擎的理论基石,Flink也不例外。
Flink自身有一套对于数据的定义,在Flink的世界中,任何类型数据的产生和传输的过程本质上都是一个事件流(数据流)。我们浏览网站的记录、购买商品的订单记录所产生的数据都随着时间的推移以数据流的形式存在。此外,Flink将数据流划分为有界流和无界流两类,如图1-3所示。
❑有界流(Bounded Stream):有界流有数据的开始,也有数据的结束,在生产中典型的案例就是离线数仓中的Hive表,一张Hive表的数据是有限的,数据有开始也有结束。
❑无界流(Unbounded Stream):无界流有数据的开始,但是没有数据的结束,其数据量是无限的、源源不断产生的,对于无界流的处理也是没有止境的,需要持续处理。
图1-3 有界流和无界流
Flink认为有界流是无界流的一种特殊形式。如图1-3所示,有界流本质上是将无界流按照一定的规则划分出一个边界得到的,边界的划分通常是按照时间进行的,比如1小时、1天。
此外,在Flink中,数据流(有界流、无界流)和数据的处理方式(批处理、流处理)不是强绑定的。
对于无界流来说,Flink可以在无界流上做流处理,这很容易理解。Flink也可以在无界流上做批处理,而这里的批处理不是通常意义上类似于Hive计算引擎的批处理,而是指Flink中的窗口计算,窗口计算会在第5章介绍。
对于有界流来说,Flink可以在有界流上做批处理,这也很容易理解,常见的Hive计算引擎就是做这件事情的。Flink也可以在有界流上做流处理,但是在生产环境中在有界流上做批处理会比流处理性能好,所以往往只在有界流上做批处理。
注意
通常情况下,我们说的实时数据处理作业,默认是指无界流上的流处理作业,其中实时的含义是数据处理过程的延迟很低。我们说的离线数据处理作业,默认是指有界流上的批处理作业,其中离线的含义是数据处理过程的延迟比较高。
1.1.3 Flink的3种应用场景
在介绍了Flink的基本定位、数据流的基本概念之后,我们来看一看Flink官方列举的3种应用。
❑数据同步型应用。
❑数据分析型应用。
❑事件驱动型应用。
接下来详细介绍这3种应用的特点,读者可以看看是否契合自己的需求场景。
1.数据同步型应用
数据同步型应用用于将数据从一个数据存储引擎转换和迁移到另一个数据存储引擎中。如图1-4所示,这类应用通常根据数据同步的周期或时效性划分为ETL(Extract-Transform-Load,抽取、转换、加载)应用和Pipeline应用,Flink同时支持这两类应用。
图1-4 ETL应用和Pipeline应用的对比
ETL应用通常会周期性触发执行,将数据从事务型数据库复制到分析型数据库或数据仓库,或者从数据存储引擎A同步到数据存储引擎B中。
举两个生产中的ETL案例。第一个案例是构建离线数仓时将原始数据同步到离线数仓,通常会将MySQL或者其他客户端、服务端的原始日志数据定时(按小时、按天)同步到Hive表中。这里的Hive表通常位于离线数仓中的ODS(Operation Data Store,贴源数据存储,又称操作数据存储)层。第二个案例是构建离线数仓时将数仓加工好的ADS(Application Data Store,应用数据存储)层中的Hive表定时同步到OLAP(On-Line Analytic Processing,在线分析处理)、K-V存储引擎中供数据报表查询使用。
Pipeline应用和ETL应用的处理过程一致,不同之处在于Pipeline应用通常是持续处理的,并非周期性触发,一般都是7×24小时持续运行,数据迁移的过程是低延迟的。例如,在电商网站中,可以通过Pipeline应用消费存储在Kafka Topic中的用户浏览、点击、加入购物车等行为的日志数据,对其中的脏数据进行过滤,对字段进行标准化,最后产出到下游数据存储引擎MySQL中,以供后续服务从MySQL中实时查询用户行为数据。
虽然Flink同时支持上述两种应用,但是通常用Flink来解决Pipeline应用场景的需求。在实际应用场景中,我们可以通过Flink SQL API+UDF解决50%的简单Pipeline需求。针对更加复杂的需求,我们可以选择更灵活的Flink DataStream API来实现。同时,Flink为ETL应用和Pipeline应用中常用的多种数据存储引擎预置了连接器(Connector),包括Kafka、Elasticsearch等数据库系统的JDBC连接器以及文件系统的连接器,用户只需简单配置即可使用。
提示
Flink DataStream API和Flink SQL API之间的关系类似于Hadoop MapReduce和Hive SQL之间的关系。
2.数据分析型应用
数据分析型应用用于支持数据分析,常见的数据处理步骤包括接入原始数据,对原始数据进行清洗、聚合处理,最后提取出有价值的信息或指标。如图1-5所示,数据分析型应用也可以根据数据计算的周期划分为离线数据分析应用和实时数据分析应用,Flink同时支持这两类应用,这也是我们总会听到Flink支持流批一体的原因。
图1-5 离线数据分析应用和实时数据分析应用的对比
离线数据分析应用通常利用批计算,定期处理和产出结果数据。比如提供给数据分析人员使用的离线数据报表应用,通常是通过定时调度Hive SQL批处理作业计算得到的。
随着需求的增加,很多场景下,批处理作业产出的延迟已经严重影响了业务的开展,业务人员希望能够实时地进行数据分析,从而及时调整、优化策略,因此实时数据分析应用诞生了。
实时数据分析应用会接入实时数据流,持续计算和更新结果数据。常见的实时数据报表应用中,数据从上游Kafka Topic实时接入,在Flink中进行实时计算,并将结果数据实时写入外部数据服务引擎MySQL,或者将结果数据维护在Flink内部的状态中。最终展示结果时,可以从MySQL中读取数据或直接查询在Flink内部的状态中保存的结果数据。
注意
虽然Flink提供了状态数据查询的能力,但是在绝大多数企业的生产环境中,考虑到数据服务稳定性等因素,不会选择用这种方式去提供服务。
3.事件驱动型应用
事件驱动型应用是一类有状态的应用,它从一个或多个事件流中读取事件数据,根据输入的数据触发计算、状态更新或产生其他外部动作。而提到事件驱动型应用,就不得不与常见的传统事务型应用做对比,如图1-6所示是传统事务型应用和事件驱动型应用的对比。
图1-6 传统事务型应用和事件驱动型应用的对比
我们用同一个案例来分析传统事务型应用和事件驱动型应用的特点。比如,在外卖平台点外卖,我们在外卖App上提交一个订单后,平台会对商家生成提醒接单的记录,商家接单之后开始备餐,然后给外卖骑手生成送单记录,外卖骑手准备去商家取餐。
首先来看上述案例按照传统事务型应用实现的效果。传统事务型应用就是我们熟知的后端应用,其特点在于数据的计算和存储是分离的,通常会使用支持事务的数据库来存储数据。以上述案例来说,用户下单之后,平台会将这条订单信息写入商家的待接单数据库(比如MySQL)中,然后给商家发一条接单提醒信息,在商家接单之后,会针对这个订单生成一条骑手送单信息,写入骑手送单数据库中,商家和骑手的后台管理系统通过访问对应的数据库表获取订单信息,然后进行后续的备单和送单操作。
接下来看上述案例按照事件驱动型应用实现的效果。简单来说事件驱动型应用就是传统事务型应用的一种升级版本,其特点在于数据计算是由一个一个的事件(数据)触发的。使用Flink实现事件驱动型应用时,通常将数据保存在处理作业的本地内存或磁盘中,在数据计算时只需要访问本地内存和磁盘,计算和存储不分离。
用户下单之后,平台会向消息队列中下发一个待处理订单事件,流处理作业读取这个事件后,会将相关的订单信息写入RocksDB(一种嵌入式存储引擎,在Flink作业本地存储状态数据),并生成一个提醒商家接单的提醒事件,待商家接单之后,会向消息队列中下发一个订单备单事件,流处理作业读取到该事件后,会将RocksDB中存储的该订单的状态标记为商家备单中,并发送待骑手接单的事件,在骑手接单之后,又会向消息队列中下发一个骑手已经接单的事件,流处理作业读取到该事件后,就可以将RocksDB中订单的状态标记为骑手正在送单中了。
在事件驱动型应用中,数据处理的过程是由一个一个的事件触发的。同时,由于将数据存储在本地了,所以该类应用通常具备高吞吐和低延迟的特点。事件驱动型应用最能体现Flink强大的处理能力,Flink的很多特性都是围绕着事件驱动型应用来设计的,包括时间、窗口、状态处理接口等,同时,Flink还拥有一个CEP(Complex Event Processing,复杂事件处理)类库,用于实现各类复杂的自定义状态机应用。
1.1.4 Flink的3个企业应用案例
在学习了Flink官方推荐的3种应用场景之后,读者不一定能准确评估自己的场景到底属于哪一类,本节将详细介绍各大企业实际使用Flink的案例,如果你的场景在内,就大胆地使用Flink吧!
1.实时数仓
实时数仓目前是Flink最广泛的应用。图1-7是典型的实时数仓和离线数仓产出链路。
图1-7 实时数仓和离线数仓的对比
实时数仓和离线数仓的加工链路大致相同,最大的区别在于实时数仓比离线数仓“快”,无论数据存储引擎还是计算引擎,从ODS层读入数据到ADS层产出数据,实时数仓可以做到秒、分钟级别的延迟,而离线数仓往往都是小时、天级别的延迟。
以图1-7中的实时数仓链路为例,通常会使用Flink从消息队列中实时消费数据,然后实时计算数据,将结果数据实时发送到消息队列当中,最终通过OLAP数据服务引擎将实时数据展示在看板上,企业应用实时数仓的典型案例就是实时报表、大屏类应用。
2.实时风控、监控
实时风控场景通常指银行业务。如图1-8所示,首先,可以通过Flink提供的各种算子加工用户的行为特征数据,比如1小时内的交易次数、登录次数、活动次数等。其次,使用Flink实时关联用户的征信、司法、税务等数据来丰富特征数据。最后,将此类特征数据存储到K-V引擎中,供风控引擎进行反欺诈判断,并将最终的结果实时反馈给用户,避免资产损失。
图1-8 银行常见的实时风控链路
3.实时推荐、机器学习
实时推荐、机器学习广泛应用于购物、搜索、广告、短视频、新闻等涉及推荐的应用场景中,和我们的生活息息相关。在购物这个典型的场景中,我们细心观察就会发现,用户在搜索完A产品后,马上就会有和A产品类似的产品推荐到用户的主页,从而减少了用户的搜索成本,优化了用户的购物体验。
实时推荐链路如图1-9所示,它主要包含三部分。
图1-9 实时推荐链路
(1)实时特征计算 使用Flink消费用户行为日志,聚合分钟级别的用户行为特征数据,比如用户过去10min浏览A产品N次,供推荐系统做用户基础行为特征查询。
(2)实时样本拼接 使用Flink消费用户行为日志,将用户在App中的整个操作行为样本按照操作时间顺序进行拼接,构建用户在App中的操作行为路径。比如将用户对于A产品的浏览、点击、收藏、加入购物车、下单等操作行为进行拼接,同时,还可以关联一些用户画像的信息,形成一个丰富的用户行为样本,供下游模型训练使用。
(3)实时模型训练 使用阿里巴巴开源的框架Alink(AI-on-Flink),消费上游Flink加工好的特征数据,进行实时模型训练,将产出的模型数据存储到模型存储引擎中,供下游实时推荐系统使用。
目前多数Flink应用场景都可以归类到上述3种应用场景中,关于Flink更多的应用场景,可以在Flink每年举办的FFA(Flink Forward Asia)大会上查看。FFA是Apache官方授权的Apache Flink亚洲社区技术会议,在一年一度的FFA中,不仅可以学习Flink社区最新的动态和发展计划,还可以了解国内外一线厂商围绕Flink生态的生产实践经验。FFA是Flink开发者和使用者不可错过的盛会。