为了加快访问速度,我们可以直接将状态保存在本地内存。当应用收到一 个新事件时,它可以从状态中读取数据,也可以更新状态。而当状态是从内存中读写的时候, 这就和访问本地变量没什么区别了,实时性可以得到极大的提升。
另外,数据规模增大时,我们也不需要做重构,只需要构建分布式集群,各自在本地计算就可以了,可扩展性也变得更好。
因为采用的是一个分布式系统,所以还需要保护本地状态,防止在故障时数据丢失。我们 可以定期地将应用状态的一致性检查点(checkpoint)存盘,写入远程的持久化存储,遇到故 障时再去读取进行恢复,这样就保证了更好的容错性。
有状态的流处理是一种通用而且灵活的设计架构,可用于许多不同的场景。具体来说,有 以下几种典型应用。
事件驱动型(Event-Driven)应用:
事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的 事件触发计算、状态更新或其他外部动作。比较典型的就是以Kafka
为代表的消息队列几乎都 是事件驱动型应用。
这其实跟传统事务处理本质上是一样的,区别在于基于有状态流处理的事件驱动应用,不 再需要查询远程数据库,而是在本地访问它们的数据, 这样在吞吐量和延迟方 面就可以有更好的性能。
另外远程持久性存储的检查点保证了应用可以从故障中恢复。检查点可以异步和增量地完 成,因此对正常计算的影响非常小。
数据分析(Data Analysis)型应用:
所谓的数据分析,就是从原始数据中提取信息和发掘规律。传统上,数据分析一般是先将 数据复制到数据仓库(Data Warehouse),然后进行批量查询。如果数据有了更新,必须将最 新数据添加到要分析的数据集中,然后重新运行查询或应用程序。
如今,Apache Hadoop 生态系统的组件,已经是许多企业大数据架构中不可或缺的组成部 分。现在的做法一般是将大量数据(如日志文件)写入Hadoop的分布式文件系统(HDFS)、 S3 或HBase等批量存储数据库,以较低的成本进行大容量存储。然后可以通过SQL-on-Hadoop 类的引擎查询和处理数据,比如大家熟悉的 Hive。这种处理方式,是典型的批处理,特点是 可以处理海量数据,但实时性较差,所以也叫离线分析。
如果我们有了一个复杂的流处理引擎,数据分析其实也可以实时执行。流式查询或应用程 序不是读取有限的数据集,而是接收实时事件流,不断生成和更新结果。结果要么写入外部数 据库,要么作为内部状态进行维护。
Apache Flink 同事支持流式与批处理的数据分析应用。与批处理分析相比,流处理分析最大的优势就是低延迟,真正实现了实时。另外,流处理 不需要去单独考虑新数据的导入和处理,实时更新本来就是流处理的基本模式。当前企业对流 式数据处理的一个热点应用就是实时数仓,很多公司正是基于Flink来实现的。
数据管道(Data Pipeline)型应用:
ETL 也就是数据的提取、转换、加载,是在存储系统之间转换和移动数据的常用方法。 在数据分析的应用中,通常会定期触发ETL任务,将数据从事务数据库系统复制到分析数据 库或数据仓库。
所谓数据管道的作用与ETL类似。它们可以转换和扩展数据,也可以在存储系统之间移 动数据。不过如果我们用流处理架构来搭建数据管道,这些工作就可以连续运行,而不需要再 去周期性触发了。比如,数据管道可以用来监控文件系统目录中的新文件,将数据写入事件日 10 志。连续数据管道的明显优势是减少了将数据移动到目的地的延迟,而且更加通用,可以用于 更多的场景。
有状态的流处理架构上其实并不复杂,很多用户基于这种思想开发出了自己的流处理系 统,这就是第一代流处理器。Apache Storm就是其中的代表。Storm可以说是开源流处理的先 锋,最早是由 Nathan Marz 和创业公司 BackType的一个团队开发的,后来才成为Apache 软 件基金会下属的项目。Storm 提供了低延迟的流处理,但是它也为实时性付出了代价:很难实 现高吞吐,而且无法保证结果的正确性。用更专业的话说,它并不能保证“精确一次” (exactly-once);即便是它能够保证的一致性级别,开销也相当大。