前言
热衷冒险的读者朋友大家好,欢迎打开这本书!此时此刻,我假定你要么是期待了解更多有关流处理的知识精髓,要么只是希望花几小时阅读有关褐鳟[1]的传奇故事。不管是哪种情况,我都向你致敬!但是,选择后者且对计算机科学没有深入理解的人,在勇敢地深入本书内容之前,可能需要做好失望的心理准备。
[1] 这里的褐鳟就是指本书封面上的动物。这是作者开玩笑的说法:读者可能会根据书的封面插图误认为本书是讲褐鳟的书。——译者注
开卷之前先定基调,有些事情我必须事先提醒一下。首先,本书有多位作者,但我们并没有尝试假装我们都以同样的风格说话和写作。就像我们是奇怪的三胞胎但恰好出生在不同的家庭。尽管这听起来很有趣,但最终的写作结果实际上会让人读起来不那么愉悦。相反,我们尝试选择以自己的语言风格编写本书,并且我们给予本书足够的自我意识,以便可以在适当的时候提到我们每个人,但又不能给予它过多的自我意识,以至于它怨恨我们只把它制作成一本书,而不是像带有苏格兰口音的机械恐龙那样更酷的东西。[2]
[2] 顺便说一句,这原本就是我们要求的动物书封面,但是O’Reilly的编辑认为这不利于制作线稿。我谨对此表示不同意,本书现在的封面上的褐鳟是一种妥协。
封面本来可能是……
本书有3位作者。
Tyler
就是我。如果本书中你没有明确地被告知是谁在说话,你可以假设是我,因为我们在本书后半部分加入了其他作者。当我写到一半想到要回去更新我已经写过的所有东西时,我基本上就像“噢,不要吧”的状态。我是谷歌公司数据处理语言与系统团队[3]的技术负责人,负责谷歌的Cloud Dataflow、Apache Beam,以及谷歌内部的数据处理系统,如Flume、MillWheel和MapReduce。我还是Apache Beam PMC的创始成员。
[3] 或者叫DataPLS,发音类似Datapals,明白了吧?
Slava
他是谷歌MillWheel团队的长期成员,后来是MillWheel系统的继任者Windmill团队的创始成员,这一至今尚未命名的系统主要负责支撑谷歌的Cloud Dataflow中的流式引擎。他是当今世界上在流处理系统中水位和时间语义方面最顶尖的专家之一。你会发现,他是第3章的作者,这不足为奇。
Reuven
他位列这份作者名单的最后一位,是因为他在流式系统领域比Slava和我都更具经验,因此我们担心他放在我们之前我们承受不了这份压力。他曾发起并领导谷歌在通用流处理引擎领域几乎所有的系统级技术创新,其中包括他投入大量精力去研究在使用细粒度检查点的系统上提供高吞吐量、低延时、精确一次的语义。你会发现,他是第5章的作者。他也是Apache Beam PMC成员。
内容导读
现在,你已经知道自己将从哪些人身上获得信息,接下来就是要了解自己将获得什么信息,让我们回到我想提到的第二件事。本书在概念上有两个主要部分,每部分有4章,每部分之后都有一章相对独立。
阅读的乐趣从第一部分“Beam模型”(第1章到第4章)开始,Beam模型最初是为谷歌的Cloud Dataflow开发的,后来作为Apache Beam项目捐赠给了Apache软件基金会。当前Beam模型在行业的大多数系统中被全部或者部分集成。第一部分的重点是高层次地讨论批加流数据处理模型,由4章组成。
● 第1章涵盖流处理的基础,建立一些术语定义,讨论流式系统的能力,区分两个重要的时间域(处理时间和事件时间),最后研究一些常见的数据处理模式。
● 第2章详细介绍针对乱序数据进行健壮的流处理所涉及的核心概念,定义、位置、时机和方法中每部分都会在具体运行示例的上下文中进行详细分析,并用动图来突出时间的维度。
● 第3章(由Slava编写)对时间进展指标、指标创建的方法以及指标在流水线中传播的方法进行深入探讨。这一章的最后详细分析两种真实场景下水位的实现。
● 第4章从第2章话题中止的地方继续讨论,深入到高级开窗和触发概念,如处理时间窗口、会话和持续触发器。
在第一部分和第二部分之间插入包含重要细节的第5章(由Reuven编写)。在第5章中,Reuven列举提供端到端精确一次(或有效一次)处理语义所带来的挑战,并详细介绍3种不同的精确一次处理方法的实现细节:Apache Flink、Apache Spark 和谷歌Cloud Dataflow。
紧接着是第二部分(第6章到第9章),这一部分对概念进行深入探讨,并研究以底层“流和表”的方式思考流处理,该思想最近由Apache Kafka社区的爱好者传播,当然源头可以追溯到数十年前的数据库社区。这部分内容也由4章组成。
● 第6章介绍流和表的基本思想,通过流和表的角度分析经典的MapReduce方法,然后尝试构建足够通用的流表理论,覆盖全部Beam模型的内容(甚至更多)。
● 第7章讨论流式流水线引入持久状态的动机,研究两种常见的隐式状态,然后分析一个实际的使用场景(广告归因),最终引出通用状态管理机制的必要特征。
● 第8章研究在关系代数和SQL中有关流式的含义,对比当前Beam模型和经典SQL中表和流之间固有的设计偏好,并且提出一组可能的路线,将健壮的流式语义并入SQL中。
● 第9章研究各种不同的连接类型,分析它们在流式上下文中的行为,最后详细研究一个有用但仍未广泛支持的流式连接使用场景:时间有效性窗口。
最后,本书的结尾是第10章,这一章纵览MapReduce数据处理系统家族的重大历史,深入讨论推进流式系统发展到今天的一些重要贡献。
要点
作为最后一点指导,如果你要我描述一下我最希望读者从本书中吸收的知识点,我会列出如下重点。
● 从本书中你能学到的唯一最重要的东西就是流表理论,以及流和表如何相互关联。其他一切知识点均是建立在上述内容之上的。我们直到第6章才开始谈这个主题。不过没关系,它值得等待,因为只有有了前面几章的铺垫,你才能更好地欣赏它的美妙。
● 时变关系启发大家新的思考方式。时变关系是流处理最典型的特征:构建流式系统所有功能的体现,并且将来自批处理的我们熟知和热爱的类似工具与上述流处理联系起来。直到第8章我们才介绍时变关系,同样,之前所有章的铺垫都是为更好地学习它们。
● 一个编写精良的分布式流式引擎是充满魔力的。这个观点其实适用于任意一个分布式系统,但是,你越深入地了解如何构建这些系统以提供处理语义(特别是来自第3章和第5章的案例研究),就越会感受到编写一个分布式流处理引擎背后的工作有多繁重了。
● LaTeX/Tikz是制作图表、动图等的工具。我对于这个工具的评价是:看似可怕、锋利,但确实是令人惊叹。我希望本书中的动图能让我们讨论的复杂话题显得更加简明,从而激励更多的人尝试LaTeX/Tikz。
排版约定
本书使用了下述排版约定。
中文楷体
表示新术语。
等宽字体(Constant
width
)
表示代码,段落内表示与代码相关的元素,如变量或函数名称、数据库、数据类型、环境变量、语句和关键字。
粗体等宽字体(Constant
width
bold
)
表示命令或用户输入的其他文本。
斜体等宽字体(Constant
width
italic
)
表示该文本应由用户提供的值或由用户根据上下文决定的值替换。
在线资源
下面提供一些相关的在线资源可以帮助你享受本书。
图
本书中所有的图可在异步社区本书对应的网页中找到。这对于自带动画效果的图特别有用。
动图是用LaTeX/Tikz绘制的,先转换为PDF,然后通过ImageMagick转换为动画GIF。对于一些刨根问底的读者,在异步社区本书对应的网页中还可以找到用于呈现动图的完整源代码和说明(包括本书、“Streaming 101”和“Streaming 102”博客文章以及原始Dataflow模型的论文)。注意,这大约有1.4万行LaTeX/Tikz代码,这些代码盘根错节地增长,我们当时并没有打算让其他读者来阅读或者修改代码。换言之,那是一张杂乱的、交织在一起的网,建议你就此打住,不要再去探索代码。
代码片段
尽管本书在很大程度是概念性的,但是仍然有很多代码和伪代码片段用于说明要点。第2章和第4章中关于功能性的核心Beam Model概念的代码,以及第7章中有关状态和计时器概念的代码,可以从异步社区本书对应的网页中获得。理解流式语义是主要目标,代码主要使用Beam PTransform/DoFn
实现并附带单元测试代码。还有一个单独的流水线实现来演示单元测试和实际流水线之间的差异。代码布局如下。
src/main/java/net/streamingbook/BeamModel.java
示例2-1至示例2-9以及示例4-3的Beam PTransform
实现,每个实现都带有额外的方法,用于在使用各章的示例数据集执行时返回预期的输出。
src/test/java/net/streamingbook/BeamModelTest.java
通过与本书中匹配的生成数据集来验证BeamModel.java中的示例PTransform
的单元测试。
src/main/java/net/streamingbook/Example2_1.java
示例2-1流水线的单机版本,可以在本地运行或使用分布式Beam运行引擎。
src/main/java/net/streamingbook/inputs.csv
Example2_1.java的样例输入文件,包含本书的数据集。
src/main/java/net/streamingbook/StateAndTimers.java
使用Beam的状态和计时器原语实现第7章中转化归因示例的Beam代码。
src/test/java/net/streamingbook/StateAndTimersTest.java
验证StateAndTimers.java中的转化归因DoFn
的单元测试。
src/main/java/net/streamingbook/ValidityWindows.java
时间有效性窗口实现。
src/main/java/net/streamingbook/Utils.java
一些共享的工具类方法。
本书是为了帮助你完成工作。一般来说,如果本书提供了示例代码,你就可以在程序和文档中直接使用它。你无须与我们联系获得授权,除非你正在复制代码的重要部分。例如,你的代码中直接使用本书中的若干代码片段不需要授权,但销售或分发O’Reilly图书示例的CD-ROM确实需要授权。通过引用本书内容或者引用示例代码以回答一些问题不需要授权,但将本书中大量的示例代码合并到你产品文档之中确实需要授权。
我们不要求注明出处,但如果注明出处我们会非常感谢。出处通常包括标题、作者、出版商和ISBN。例如“Streaming Systems by Tyler Akidau, Slava Chernyak, and Reuven Lax (O’Reilly). Copyright 2018 O’Reilly Media, Inc., 978-1-491-98387-4.”。
如果觉得使用代码示例超出了合理使用或上面我们所给出的权限,请随时通过permissions@oreilly.com与我们联系。
我们的联系方式
如果想就本书发表评论或有任何疑问,敬请联系O’Reilly出版社。
美国:
O’Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
中国:
北京市西城区西直门南大街2 号成铭大厦C 座807 室(100035)
奥莱利技术咨询(北京)有限公司
我们还为本书建立了一个网页,其中包含勘误表、示例和其他额外的信息。你可以在O’Reilly官方网站访问本书对应的网页。
关于本书的技术性问题或建议,请发电子邮件到errata@oreilly.com。
要查看更多我们的书籍、课程、会议和最新动态等信息,可访问O’Reilly官方网站。
致谢
最后也是最重要的一点是,许多人都特别出色,我们要在这里感谢他们中的一部分,感谢他们对我们撰写这本书给予的帮助。
本书的内容提炼了谷歌、整个行业以及整个学术界无数绝顶聪明人的工作精华。我们对他们表示诚挚的感谢,但遗憾的是我们无法将这些帮助过我们的人一一列出来道谢。
在谷歌的同事中,DataPLS团队(以及这一团队各个前身团队,包括Flume、MillWheel、MapReduce等)中的所有人都功不可没,多年来,他们帮助我们让这些想法落地实现。我们尤其要感谢下面这些人。
● 感谢Paul Nordstrom和来自MillWheel黄金期的MillWheel团队的其他成员Alex Amto、Alex Balikov、Kaya Bekirğlu、Josh Haberman、Tim Hollingsworth、Ilya Maykov、Sam McVeety、Daniel Mills和Sam Whittle建立这样一套全面的、健壮的、可伸缩的底层原语,我们在这些原语之上能够构建本书中讨论的更高级的模型。如果没有他们的远见和技能,今天大规模流处理领域将截然不同。
● 感谢Craig Chambers、Frances Perry、Robert Bradshaw、Ashish Raniwala和Flume团队的其他成员通过Flume实现一套易于表达且功能强大的大数据处理基础,我们基于此统一了流式世界。
● 感谢Sam McVeety,MillWheel论文的主要作者,这篇论文第一次使我们这个令人惊叹的小项目声名远扬。
● 感谢Grzegorz Czajkowski在很多项目交付期限和其他紧急事项迫在眉睫的情况下还一直支持我们的技术布道工作。
从更大视野看,大量的功劳归于Apache Beam、Apache Calcite、Apache Kafka、Apache Flink、Apache Spark和Apache Storm社区的每个人。在过去10多年中,这些项目为推动全世界流处理的最先进技术做出了重大贡献。
为了更加具体地表示感谢,我们要感谢下面这些人。
● 感谢Martin Kleppmann,带头倡导“流和表”的思维方式,并投入大量时间为本书每章的初稿提供了富有见地的技术意见和编辑意见。你是一个充满创意、各方面都非常出色的人。
● 感谢Julian Hyde,感谢你充满洞察的愿景以及对流式SQL的异常热情。
● 感谢Jay Kreps,感谢你与Lambda架构“暴政”做斗争,你原创的“Questioning the Lambda Architecture”文章让Tyler顿时精神抖擞,被感染到也加入了这场辩论。
● 感谢Stephan Ewen、Kostas Tzoumas、Fabian Hueske、Aljoscha Krettek、Robert Metzger、Kostas Kloudas、Jamie Grier、Max Michels和dataArtisans[4]大家庭的其余同事。一直以来,你们总是以开放和协作的方式去推动流式系统发展。感谢大家,流式世界因为你们变得更加美好。
[4] dataArtisans被阿里巴巴收购后,已改名为Ververica。——译者注
● 感谢Jesse Anderson,感谢你勤奋审稿和热情的拥抱。如果见到你,我一定给你一个大大的拥抱。
● 感谢Danny Yuan、Sid Anand、Wes Reisz以及卓越的QCon开发者大会,使我们第一次有机会在2014年旧金山QCon大会上对业界公开谈论我们的工作。
● 感谢O’Reilly的Ben Lorica和标志性的Strata数据会议,一再支持我们努力传播流处理技术,无论是在线上,还是通过书籍,或是亲自宣传。
● 感谢整个Apache Beam社区,特别是我们的提交者(committer),帮助推进Beam的愿景,感谢Ahmet Altay、Amit Sela、Aviem Zur、Ben Chambers、Griselda Cuevas、Chamikara Jayalath、Davor Bonaci、Dan Halperin、Etienne Chauchot、Frances Perry、Ismaël Mejía、Jason Kuster、Jean-Baptiste Onofré、Jesse Anderson、Eugene Kirpichov、Josh Wills、Kenneth Knowles、Luke Cwik、Jingsong Lee、Manu Zhang、Melissa Pashniak、Mingmin Xu、Max Michels、Pablo Estrada、Pei He、Robert Bradshaw、Stephan Ewen、Stas Levin、Thomas Groh、Thomas Weise和James Xu。
如果不对不知疲倦的审稿人表达感谢,那这篇致谢绝对是不完整的,那些充满讲解的评注让平凡的东西变得卓越。感谢Jesse Anderson、Grzegorz Czajkowski、Marián Dvorský、Stephan Ewen、Rafael J. Fernández-Moctezuma、Martin Kleppmann、Kenneth Knowles、Sam McVeety、Mosha Pasumansky、Frances Perry、Jelena Pjesivac-Grbovic、Jeff Shute和William Vambenepe,你们就像是《回到未来2》中时光车的核融合装置。
当然,我们还要感谢我们的创作和出版支持团队。
● 感谢我们的首任编辑Marie Beaugureau给予我们的帮助和支持,以使该项目得以开展,并对我颠覆编辑规范保持一贯的耐心。我们想你!
● 感谢我们的继任编辑Jeff Bleiel接管了我们整个出版项目,并且帮助我们完成了这个项目,感谢你对我们可能无法在最后宽松的期限内完成书稿保持了极大耐心。最终我们完成了!
● 感谢我们的文字编辑Bob Russell比任何人都更仔细地阅读了我们的书。我向你对语法、标点、词汇和Adobe Acrobat批注的熟练掌握表示敬意。
● 感谢我们的制作编辑Nick Adams帮助我们将一团乱如麻的HTML代码整理成一件制作精良的出版物。当我要求你手动忽略Bob的多次有关将我们使用的术语“数据”从复数改为单数的建议时,你没有生我的气。你让本书看起来比我希望的还要好看,谢谢。
● 感谢我们的索引编制者Ellen Trotman-Zaig以某种方式将一个错综复杂的参考网络处理成一个有用且全面的索引。我敬畏你对细节的关注。
● 感谢我们的插图画师Rebecca Panzer美化我们的静态图,并向Nick保证我不需要花更多的周末时间来研究如何重构我的动画以调整为更大的字体。
● 感谢我们的校对员Kim Cofer指出我们的草率和不一致之处,这样其他读者就不需要再受一次折磨。
Tyler想感谢下面这些人。
● 感谢我的合著者Reuven Lax和Slava Chernyak,以前所未有的方式将想法和章节付诸实践。
● 感谢Rob Schlender要在机器人接管世界前给我买一瓶苏格兰威士忌。敬时尚!
● 感谢我的叔叔 Randy Bowen,让我发现我是多么喜欢计算机,尤其是那张自制的Pov-Ray2.x软盘,为我打开了一个全新的世界。
● 感谢我的父母David和Marty Dauwalder,没有你们的奉献精神和难以置信的毅力,这一切都不可能实现。你们是有史以来最好的父母!
● 感谢David L. Vlasuk博士,没有你,我今天就不会在这里了。谢谢你给予我的所有帮助。
● 感谢我的家人Shaina、Romi和Lone Akidau,尽管写作占用了我许多夜晚和周末,但你们仍坚定地支持我完成了这项艰巨的任务。我永远爱你们。
● 感谢我忠实的写作伙伴Kiyoshi,尽管我们一起写这本书的时候,你要么在睡觉,要么在邮差到来时狂叫,但不得不说你做得毫无瑕疵,而且似乎不费吹灰之力。你是你小狗家族的骄傲。
Slava要感谢下面这些人。
● 感谢在MillWheel和后续的流式Dataflow中的水位以及这些系统的许多其他部分的代码设计人员和共同参与者Josh Haberman、Sam Whittle和Daniel Mills。像这样复杂的系统从来都不是凭空设计,没有你们每个人的思考和努力,我们今天不会有如此成就。
● 感谢来自Ververica的Stephan Ewen帮助我认识并理解了Apache Flink的水位机制。
Reuven要感谢下面这些人。
● 感谢Paul Nordstrom的远见,感谢Sam Whittle、Sam McVeetty、Slava Chernyak、Josh Haberman、Daniel Mills、Kaya Bekirog Lu、Alex Balikov、Tim Hollingsworth、Alex Amato和Ilya Maykov在构建最初的MillWheel系统以及撰写后续论文付出的所有努力。
● 感谢来自Ververica的Stephan Ewen帮助审阅了第5章,以及针对Apache Flink内部机制给出的宝贵反馈。
最后,我们都要感谢亲爱的读者,感谢你愿意花钱购买本书,听我们喋喋不休地谈论我们要做的和要玩的东西。把我们所知所想写下来实为人生快事,我们竭尽全力确保你购买本书是物有所值的。但是,如果出于某种原因你不喜欢它……好吧,希望你买了纸质书,这样你至少可以把它扔到房间里,一段时间后当作旧书卖掉。