第十二章:数据系统展望#
复杂的系统都是从简单的系统演进而来的,从另一个角度来说,开始就很复杂的系统是根本不会被设计出来的。
— 约翰·加尔, Systemantics (1975)
早起发布读者须知
作为早期发布电子书,您可获取书籍的最初版本——作者写作时的原始未编辑内容——因此您能够早在这些书籍正式发布之前,就充分利用这些技术内容。
这将是本书终版的第十二章。本书的GitHub代码库位于 https://github.com/ept/ddia2-feedback.
若您希望积极参与此版草稿的审阅与评论工作,请通过GitHub联系我们。#
在第十一章中我们讨论了批处理-它是将一组文件作为输出然后在产出一组新的文件的技术。输出是派生数据(derived data)的一种形式;运行在批处理流程中的数据在必要的时候是可以再次生成的。我们了解到了这一简单却强大的理念是如何被应用于构建搜索索引、推荐系统、分析工具等领域。
但是,在第十一章中我们始终假设的一个命题是:输入是有边界的-即已知且有限的大小-所以批处理程序知道它何时完成了输入信息的读取。例如MapReduce的核心排序操作必须完整的读取所有的输入后才能开始输出结果:这就有可能会发生一个很小的键值数据记录很晚才被输入,因为这个小键值记录需要我们第一个输出,所以我们的输出不能很早进行(要等待这个最小键值输入后才能开始输出操作)。
实际上,很多数据之所以无边界是因为它们是随着时间的推移慢慢到达的:你的用户昨天和今天产生了数据,它明天还会继续产生更多的数据。除非你歇业,否者这个过程永远不会停止,所以在一定意义上,数据集从来不会有“完成(complete)”态[1]。因此,批处理程序必须人工的将数据划分为固定区间的数据块:例如:在每天结束的时候处理一天的有效数据,或者在每个小时结束后处理这一小时的有效数据。
以天为维度的批处理问题在于输入数据的变化只有在一天后才会对输出的结果有影响,这对很多急性子的用户来说太慢了。为了减少延迟,我们可以更频繁的执行批处理程序-例如每一秒都执行一次来处理上一秒的有效数据,甚至于说连续的,完全不划分固定区间,每个事件来临就立即处理。这便是「流处理」(stream processing)背后的思想。
通常,“流”指的是随着时间推移而逐渐可用的数据。这个概念出现在很多地方:在Unix的标准输入(stdin)和标准输出(stdout)中,编程语言(lazy lists)[],文件系统API(例如Java的FileInputStream),TCP连接,通过互联网传输的音频和视频等等。
本章,我们将把事件流(event streams)视为一种数据管理机制:一种对应于我们上一章所介绍的,一种无界的,持续增量处理的批数据处理方式。我们首先会讨论流在网络中怎样表示、存储和传输。在“数据库与流”中我们会讨论流和数据库之间的联系。最后,在“流处理”中,我们会继续探讨处理这些流的方法和工具,以及它们用来构建应用的方式。
传输事件流#
在批处理的世界,