学习Flink:实践培训
本次培训的目标和范围
本培训介绍了Apache Flink,包括足够的内容让你开始编写可扩展的流式ETL,分析和事件驱动的应用程序,同时省略了很多(最终重要的)细节。本书的重点是为Flink管理状态和时间的API提供直接的介绍,希望在掌握了这些基础知识后,你能更好地从更详细的参考文档中获取其余需要了解的内容。每一节末尾的链接将引导你到可以学习更多知识的地方。
具体来说,您将学习
- 如何实现流数据处理管道
- Flink如何以及为何管理国家
- 如何使用事件时间来持续计算准确的分析结果?
- 如何在连续流上构建事件驱动的应用程序?
- Flink是如何提供具有精确只读语义的容错、有状态的流处理的?
本培训主要介绍四个关键概念:流数据的连续处理、事件时间、有状态的流处理和状态快照。本页介绍了这些概念。
注 伴随本培训的是一套实践练习,它将指导你学习如何使用所介绍的概念。每一节的最后都提供了相关练习的链接。
流处理
流是数据的天然栖息地。无论是来自网络服务器的事件,还是来自股票交易所的交易,或者是来自工厂车间机器的传感器读数,数据都是作为流的一部分被创建的。但当你分析数据时,你可以围绕有界流或无界流来组织处理,你选择哪种范式都会产生深远的影响。
当你处理一个有边界的数据流时,批处理是工作的范式。在这种操作模式下,你可以选择在产生任何结果之前摄取整个数据集,这意味着,例如,可以对数据进行排序,计算全局统计,或产生一个总结所有输入的最终报告。
另一方面,流处理涉及无边界的数据流。至少在概念上,输入可能永远不会结束,因此你不得不在数据到达时持续处理数据。
在Flink中,应用程序由流式数据流组成,这些数据流可以通过用户定义的操作符进行转换。这些数据流形成定向图,从一个或多个源开始,到一个或多个汇结束。
通常,程序中的变换和数据流中的操作符之间是一对一的对应关系。但有时,一个变换可能由多个运算符组成。
一个应用程序可能会消耗来自流媒体源的实时数据,如消息队列或分布式日志,如Apache Kafka或Kinesis。但flink也可以消耗来自各种数据源的有界历史数据。同样,Flink应用正在产生的结果流也可以被发送到各种各样的系统,这些系统可以作为汇接。
并行数据流
Flink中的程序本质上是并行和分布式的。在执行过程中,一个流有一个或多个流分区,每个操作员有一个或多个操作员子任务。操作员子任务相互独立,在不同的线程中执行,也可能在不同的机器或容器上执行。
运算符子任务的数量就是该特定运算符的并行性。同一程序的不同运算符可能具有不同的并行性水平。
流可以在两个操作符之间以一对一(或转发)的模式或以再分配的模式传输数据。
- 一对一的流(例如上图中Source和map()操作符之间)保留了元素的分区和排序。这意味着map()操作符的子任务[1]将看到与Source操作符的子任务[1]所产生的元素顺序相同的元素。
- 重新分配流(如上面map()和keyBy/window之间,以及keyBy/window和Sink之间)会改变流的分区。每个操作者子任务都会根据所选的转换将数据发送到不同的目标子任务。例如keyBy()(通过散列密钥来重新分区)、broadcast()或rebalance()(随机重新分区)。在重分配交换中,元素之间的排序只在每一对发送和接收子任务中被保留(例如,map()的子任务[1]和keyBy/window的子任务[2])。所以,例如,上面所示的keyBy/window和Sink运算符之间的再分配,引入了关于不同密钥的聚合结果到达Sink的顺序的非确定性。
及时的流式处理
对于大多数流式应用来说,能够用处理实时数据的相同代码重新处理历史数据是非常有价值的--无论如何,都能产生确定性的、一致的结果。
此外,关注事件发生的顺序,而不是事件交付处理的顺序,并且能够推理出一组事件何时(或应该)完成也是至关重要的。例如,考虑电子商务交易,或金融贸易中涉及的一系列事件。
通过使用记录在数据流中的事件时间戳,而不是使用处理数据的机器的时钟,可以满足这些及时流处理的要求。
有状态的流处理
Flink的操作可以是有状态的。这意味着一个事件的处理方式可以取决于之前所有事件的累积效果。状态可以用于一些简单的事情,例如计算每分钟的事件以显示在仪表板上,或者用于一些更复杂的事情,例如计算欺诈检测模型的功能。
一个Flink应用是在分布式集群上并行运行的。一个给定的操作者的各种并行实例将以不同的线程独立执行,一般来说,它们将在不同的机器上运行。
一个有状态操作符的并行实例集实际上是一个分片的键值存储。每一个并行实例负责处理一组特定键的事件,这些键的状态被保存在本地。
下图显示了一个作业,在作业图中的前三个操作符上运行的并行度为2,终止于一个并行度为1的sink。第三个操作符是有状态的,你可以看到在第二个和第三个操作符之间发生了一个完全连接的网络洗牌。这是在通过一些键来对流进行分区,这样所有需要一起处理的事件将一起被处理。
状态总是在本地访问,这有助于Flink应用实现高吞吐量和低延迟。您可以选择将状态保存在JVM堆上,如果状态太大,则保存在高效组织的磁盘数据结构中。
通过状态快照进行容错
Flink能够通过状态快照和流重放的组合,提供容错、精确的一次性语义。这些快照捕获了分布式管道的整个状态,记录了进入输入队列的偏移以及整个作业图中因摄取了该点数据而产生的状态。当发生故障时,源会被重卷,状态被恢复,并恢复处理。如上所述,这些状态快照是异步捕获的,不会妨碍正在进行的处理。