剑指大数据:Flink学习精要(Scala版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3.3 有状态的流处理

不难想到,如果我们对事件流的处理非常简单,比如收到一条请求就返回一个“收到”,就可以省去数据库的查询和更新了,但是这样的处理是没什么实际意义的。在现实应用中,往往还需要一些额外数据。此时,可以把需要的额外数据保存成一个“状态”,然后针对这条数据进行处理并更新状态。在传统架构中,这个状态是保存在数据库里的,这就是所谓的有状态的流处理。

为了加快访问速度,可以直接将状态保存在本地内存中,如图1-6所示。当应用收到一个新事件时,它可以从状态中读取数据,也可以更新状态;而当状态从内存中读/写的时候,就和访问本地变量没什么区别了,实时性可以得到极大的提升。

另外,当数据规模增大时,我们也不需要重构,只需要构建分布式集群,各自在本地计算就可以了,可扩展性也变得更好。

因为采用的是一个分布式系统,所以还需要保护本地状态,防止发生故障时丢失数据。我们可以定期地将应用状态的一致性检查点存盘,写入远程持久化存储中,遇到故障时再去读取而进行恢复,保证更好的容错性。

图1-6 有状态的流处理

有状态的流处理是一种通用且灵活的设计架构,可用于许多不同的场景,具体来说,有以下几种典型应用。

1.事件驱动型(Event-Driven)应用

事件驱动型应用是一类具有状态的应用,它从一个或多个事件流中提取数据,并根据到来的事件触发计算、状态更新或其他外部动作,比较典型的就是以Kafka为代表的消息队列,几乎都是事件驱动型应用。

这其实跟传统事务处理在本质上是一样的,区别在于基于有状态的流处理的事件驱动应用不再需要查询远程数据库,而是在本地访问它们的数据,如图1-7所示,这样在吞吐量和延迟方面就可以有更好的性能。

另外,远程持久化存储的检查点保证了应用可以从故障中恢复。检查点可以异步和增量地完成,因此对正常计算的影响非常小。

图1-7 传统事务处理与事件驱动型应用对比

2.数据分析(Data Analysis)型应用

所谓数据分析,就是指从原始数据中提取信息和发掘规律。传统的数据分析一般先将数据复制到数据仓库(Data Warehouse)中,进行批量查询,如果数据有了更新,就必须将最新数据添加到要分析的数据集中,然后重新运行查询或应用程序。

如今,Apache Hadoop生态系统的组件已经是许多企业大数据架构中不可或缺的组成部分。因此,现在的做法一般是将大量数据(如日志文件)写入Hadoop的分布式文件系统(HDFS)、S3或HBase等批量存储数据库中,以较低的成本进行大容量存储;然后可以通过SQL-on-Hadoop类的引擎查询和处理数据,如大家熟悉的Hive。这种处理方式是典型的批处理,其特点是可以处理海量数据,但实时性较差,因此也叫离线分析。

如果我们有一个复杂的流处理引擎,那么数据分析其实也可以实时执行。流式查询或应用程序不再读取有限的数据集,而是接收实时事件流,不断生成和更新结果,结果要么被写入外部数据库,要么被作为内部状态进行维护。

Apache Flink同时支持批处理与流处理的数据分析应用,如图1-8所示。

图1-8 数据分析型应用的批处理与流处理

与批处理分析相比,流处理分析最大的优势就是低延迟,真正实现了实时。另外,流处理不需要单独考虑新数据的导入和处理,实时更新本来就是流处理的基本模式。当前企业对流式数据处理的一个热点应用就是实时数据仓库,很多企业正是基于Flink来实现的。

3.数据管道(Data Pipeline)型应用

ETL即数据的提取、转换、加载,是在存储系统之间转换和移动数据的常用方法。在数据分析应用中,通常会定期触发ETL任务,将数据从事务数据库系统复制到分析数据库或数据仓库中。

数据管道的作用与ETL的作用类似,可以转换和扩展数据,也可以在存储系统之间移动数据。不过,如果我们用流处理架构搭建数据管道,那么这些工作就可以连续运行,而不需要再去周期性触发了。例如,数据管道可以用来监控文件系统目录中的新文件,将数据写入事件日志中。连续数据管道的明显优势是降低了将数据移动到目的地的延迟,而且更加通用,可应用于更多的场景。

周期性ETL与数据管道的区别如图1-9所示。

图1-9 周期性ETL与数据管道的区别

有状态的流处理架构其实并不复杂,很多用户基于这种思想开发了自己的流处理系统,这就是第一代流处理器,Apache Storm就是其中的代表。Storm可以说是开源流处理的先锋,最早是由Nathan Marz和BackType的一个团队开发的,后来才成为Apache软件基金会的下属项目。Storm提供了低延迟的流处理,但是它也为实时性付出了代价:很难实现高吞吐,而且无法保证结果的正确性。用更专业的话说,它并不能保证“精确一次”(exactly-once);即便是它能够保证的一致性级别,开销也相当大。状态一致性和exactly-once会在后续章节展开讨论。