书名:Kafka实战
ISBN:978-7-115-61444-5
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 [美]迪伦•斯科特(Dylan Scott) 维克托•盖莫夫(Viktor Gamov) 戴夫•克莱因(Dave Klein)
译 薛命灯
责任编辑 谢晓芳
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
读者服务:
微信扫码关注【异步社区】微信公众号,回复“e61444”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
本书旨在介绍Kafka的核心功能,以及如何在实际项目中使用它。本书主要内容包括Kafka的核心概念,如何使用Kafka Connect设置和执行基本ETL任务,如何将Kafka用于大型数据项目,如何执行管理任务,如何生成和使用事件流,如何在Java应用程序中使用Kafka,如何将Kafka实现为消息队列等。通过阅读本书,读者应该很快就会掌握如何在日常工作流程中使用 Kafka,还可以开始深入研究更高级的 Kafka 主题。
本书适合软件开发人员阅读,也可作为计算机相关专业的教材。
谨以本书献给Harper,他每天都让我感到骄傲,也献给Noelle,她每天都为我们的家庭带来更多的快乐,也献给我的父母、姐姐和妻子,他们一直是我坚强的后盾。
——Dylan
谨以本书献给我的妻子Maria,感谢她在我写作本书的过程中给予我的支持。这是一项非常耗时的任务,为了写作本书,我需要像海绵一样挤出时间。没有她的鼓励,就不会有现在的成果。此外,我还想把本书献给我的孩子Andrew和Michael,也要感谢他们,他们是如此天真可爱。当人们问他们爸爸在哪里工作时,他们会说:“爸爸在Kafka工作。”
——Viktor
谨以本书献给我的家人——Debbie、Zachary、Abigail、Benjamin、Sarah、Solomon、Hannah、Joanna、Rebekah、Susanna、Noah、Samuel、Gideon、Joshua和Daniel。最后,我所做的每一件事都是为了让生活更美好。
——Dave
首先我想对我的家人说声谢谢。我对他们每天给予我的支持和爱感激不尽——我爱他们。感谢Dan和Debbie,他们一直是我坚实的后盾。感谢Sarah、Harper和Noelle,我无法用寥寥数语来表达我对他们的爱和自豪之情以及他们所给予我的支持。感谢DG一家,也谢谢JC。
我还要感谢我的一些同事和技术伙伴,他们不断激励我,推动了本书的写作进程,他们分别是Becky Campbell、Adam Doman、Jason Fehr、Dan Russell、Robert Abeyta和Jeremy Castle。谢谢Jabulani Simplisio Chibaya,不仅感谢他的评论,也感谢他亲切的话语。
我要感谢我的妻子,感谢她给予我的支持。还要感谢Confluent的Ale Murray、Yeva Byzek、Robin Moffatt和Tim Berglund。他们正在为强大的Apache Kafka社区贡献着不可思议的工作成果!
我要感谢Dylan和Viktor,他们带着我一起体验这场令人兴奋的旅程。
我们要感谢Manning出版社的编辑Toni Arritola,本书的出版离不开他的指导。我们也要感谢在Toni接手之前的第一任编辑Kristen Watterson,感谢技术编辑Raphael Villela、Nickie Buckner、Felipe Esteban、Vildoso Castillo、Mayur Patil、Valentin Crettaz和William Rudenmalm。我们也感谢Chuck Larson在图片方面给予的巨大帮助,以及Sumant Tambe对代码的审校。
Manning出版社的团队在从本书出版到推广的整个过程中提供了非常大的帮助。经过编辑、修订,本书的内容和源代码中仍然可能存在一些拼写错误或问题(至少我们还没有见过一本不带勘误表的书),但这个团队确实帮忙将这些错误的数量降到了最低。
我们要感谢Nathan Marz、Michael Noll、Janakiram MSV、Bill Bejeck、Gunnar Morling、Robin Moffatt、Henry Cai、Martin Fowler、Alexander Dean、Valentin Crettaz和Anyi Li,他们非常乐于让我们提及他们的工作,并提供了非常好的建议和反馈。
感谢饶军愿意花时间为本书写序,我们为此感到很荣幸。非常感谢!
我们非常感谢整个Kafka社区(包括Jay Kreps、Neha Narkhede和饶军)和Confluent的团队,他们推动了Kafka的发展,并允许我们在本书中使用他们提供的一些材料。至少,我们希望我们的工作能够鼓励开发人员一起来关注Kafka。
最后,我们要感谢所有的审校人员——Bryce Darling、Christopher Bailey、Cicero Zandona、Conor Redmond、Dan Russell、David Krief、Felipe Esteban、Vildoso Castillo、Finn Newick、Florin-Gabriel Barbuceanu、Gregor Rayman、Jason Fehr、Javier Collado Cabeza、Jon Moore、Jorge Esteban Quilcate Otoya、Joshua Horwitz、Madhanmohan Savadamuthu、Michele Mauro、Peter Perlepes、Roman Levchenko、Sanket Naik、Shobha Iyer、Sumant Tambe、Viton Vitanis和William Rudenmalm,他们的建议让本书变得更好。
我们可能会漏掉一些名字,如果有,希望他们能够原谅我们。我们对他们感激不尽。
Dylan Scott是一名软件开发者,拥有十多年Java和Perl开发经验。在第一次将Kafka作为大型数据迁移项目的消息系统之后,Dylan又进一步探索Kafka和流式处理的世界。他使用过各种技术和消息队列产品,包括Mule、RabbitMQ、MQSeries和Kafka。Dylan拥有Sun Java SE 1.6、Oracle Web EE 6、Neo4j和Jenkins Engineer等方面的证书。
Viktor Gamov就职于Confluent公司。Confluent就是那家开发基于Kafka的事件流平台的公司。在Viktor的整个职业生涯中,他使用开源技术构建企业应用程序架构,积累了全面的专业知识。他喜欢帮助架构师与开发人员设计和开发低延迟、可伸缩且高可用的分布式系统。Viktor不仅是分布式系统、流式数据、JVM和DevOps 等主题的专业会议讲师,还是JavaOne、Devoxx、OSCON、QCon等活动的常客。他是Enterprise Web Development(O’Reilly出版社)一书的合著者。
Dave Klein担任过开发者、架构师、项目经理、作家、培训师、会议组织者等,主要研究方向是Kafka事件流。
自2011年第一次发布以来,Kafka促成了一种新的动态数据系统类型。现在,它已经成为无数现代事件驱动应用程序的基础。本书展示了基于Kafka设计和实现事件驱动应用程序的技能。本书作者拥有多年实际使用Kafka的经验,本书中的干货让它变得与众不同。
我们不禁要问:“为什么我们需要Kafka?”从历史上看,大多数应用程序以静态数据系统为基础。每次发生了一些有趣的事件,它们会立即保存在这些系统中,但对这些事件的使用发生在未来,要么在用户主动请求获取信息时,要么在批处理作业中。
在动态数据系统中,应用程序预先定义了当新事件发生时它们需要做些什么。当新事件发生时,它们会近乎实时地自动反映在应用程序中。这种事件驱动应用程序对于企业来说有很大的吸引力,因为企业能够更快地从数据中获得新的结论。转向事件驱动的应用程序需要人们在思维模式上做出改变,但这并非易事。本书不仅为理解事件驱动思维模式提供全面的资源,还提供真实的示例。
本书解释Kafka的工作原理,重点介绍开发人员如何用Kafka构建端到端的事件驱动应用程序。你将了解构建一个基本的Kafka应用程序所需的组件,以及如何使用Kafka Streams和ksqlDB等开发库构建更高级的应用程序。除构建应用程序之外,本书还将介绍如何在生产环境中运行它们。
我希望你像我一样喜欢本书。愿你能愉快地处理事件流!
—— 饶军,Confluent联合创始人
在谈到撰写一本技术图书时,我们经常会被问及这样一个问题:为什么要写成书?至少对于Dylan来说,阅读一直是他最喜欢的学习方式之一。另外,这也是为了怀念他读过的第一本编程图书,Andrew L. Johnson撰写的Elements of Programming with Perl(由Manning出版社出版)。他对该书中的内容很感兴趣,和作者一起浏览书中每一页内容充满了乐趣。我们也希望能够捕获到一些与使用Kafka和阅读Kafka资料有关的实用内容。
在第一次使用Kafka时,学习到新东西的兴奋感触动了我们。在我们看来,Kafka不同于我们以前使用过的消息代理或企业服务总线(Enterprise Service Bus,ESB)。快速构建生产者和消费者、重新处理数据,以及消费者快速处理数据但不影响其他消费者,这些功能解决了我们在过去的开发中遇到的痛点,并在我们研究Kafka时给我们留下了深刻印象。
Kafka改变了数据平台标准,促使批处理和ETL工作流接近实时数据反馈。因为这很可能是企业用户所熟悉的旧数据架构的一种转型,所以我们想从之前不了解Kafka的用户的角度出发,帮助他们培养使用Kafka生产者和消费者的能力,并执行基本的Kafka开发和管理任务。在本书的第三部分,我们希望读者能够基于新学到的核心Kafka知识深入研究更高级的Kafka主题,如集群监控、指标和多站点数据复制。
请记住,技术在不断更新,Kafka也会继续演变,希望在你阅读到本书时它会变得更好。我们希望本书能够为你提供一条轻松学习Kafka基础知识的路径。
我们写本书是为了指导开发人员使用Kafka。本书提供了一些示例,讲解一些关键知识点和用来改变Kafka默认行为以满足特定需求的配置参数。Kafka的核心是关注基础知识,以及如何基于Kafka构建其他产品,如Kafka Streams和ksqlDB。本书会展示如何使用Kafka来满足各种业务需求,读者在阅读完本书后应该能够熟悉它,并知道怎样着手满足自己的需求。
本书是为任何一位想学习流式处理的开发者而准备的。虽然本书不要求读者具备Kafka的先验知识,但如果懂得一些基本的命令行或终端知识会很有帮助。Kafka提供了一些强大的命令行工具,用户至少应该能够在命令行提示符下执行这些命令。
掌握一些Java编程技能或各种语言的编程概念不仅有助于读者从本书中得到更多的收获,还有助于他们更好地理解本书中的代码示例,因为这些代码主要采用了Java 11(以及Java 8)的编码风格。尽管不是必需的,但如果读者对分布式应用程序架构的一般性知识有所了解,也会有所裨益。例如,对数据复制和故障了解得越多,就越容易了解Kafka是如何使用副本的。
本书分为3部分,共12章。第一部分介绍Kafka的概念模型,并讨论为什么你会在现实世界中使用Kafka。
● 第1章概述Kafka,并讲述一些真实的应用场景。
● 第2章介绍Kafka的高级架构,以及一些重要的术语。
第二部分介绍Kafka的核心部分——客户端和集群。
● 第3章讨论什么时候应该在项目中使用Kafka,以及如何设计一个新项目。该章还讲述在启动Kafka项目时(而不是在以后)就应该考虑使用Schema。
● 第4章详细介绍如何创建生产者客户端,以及可以通过哪些参数影响数据进入Kafka集群的方式。
● 第5章介绍如何使用消费者客户端从Kafka获取数据。该章还讲述偏移量和重新处理数据的概念,这些都得益于Kafka保留消息的特性。
● 第6章讨论Broker在集群中的作用,以及它们如何与客户端交互。该章还探讨各种Broker组件,如控制器和副本。
● 第7章探讨主题和分区的概念,包括如何压实主题和存储分区。
● 第8章讨论用于处理需要保留或重新处理的数据的工具和架构。如果需要保留数据数月或数年,可能需要考虑使用集群之外的存储系统。
● 第9章介绍有助于保持集群健康的日志、指标和管理任务。
第三部分将我们的关注点从Kafka的核心部分转移到如何改进运行的集群上。
● 第10章介绍如何通过安全套接字层、访问控制列表和配额等特性增强Kafka集群。
● 第11章深入探讨Schema Registry,以及如何用它促进数据演化,保持数据集前后版本的兼容性。尽管这是企业级应用程序常用的特性,但它对于随时间发生变化的数据来说是很有用的。
● 第12章介绍Kafka Streams和ksqlDB。这些产品都是基于Kafka的核心部分而构建的。Kafka Streams和ksqlDB都是大主题,我们只提供了足够的细节来帮助你着手了解这些Kafka解决方案。
本书包含许多源代码,有的是编号的代码清单,有的嵌套在正文中。源代码都使用了等宽字体进行格式化,以便与普通文本区分。大多数情况下,初始源代码经过重新格式化后,我们添加了换行符,并重新修改了缩进,以适应本书的版式。有些时候,这些还不够,代码清单还包含行延续标记(➥)。代码清单中有很多代码注释,用于说明一些重要的概念。
许多代码示例并不完整,它们只是与当前正在讨论的内容相关的摘录。你可以在GitHub网站(搜索“Kafka-In-Action-Book/Kafka-In-Action-Source-Code”)和Manning出版社网站(搜索“books/kafka-in-action”)上找到本书配套的代码。
下面的在线资源将随着Kafka的演变而发生变化。在大多数情况下,对应网站也提供了过去版本的文档。
● Apache Kafka文档,参见Apache Kafka网站。
● Confluent文档,参见Confluent Documentation网站。
● Confluent开发者文档,参见Confluent开发者门户网站。
本书封面上的人物插图名为“马达加斯加女人”。插图取自 19 世纪法国一个反映地区服饰风俗的作品集,作者是Sylvain Maréchal。其中每幅插图都是手工精心绘制并上色的。这些丰富多样的服饰生动地展现了200年前世界上不同城镇和地区的文化差异。尽管人们相互隔绝,说的是不同的语言,但是仅仅从穿着就很容易分辨出他们住在城镇还是乡间,知悉他们的工作和身份。
从那以后,着装规范发生了变化,当时丰富多彩的地域多样性已经逐渐消失了。现在很难从服装上区分不同大洲的居民,更不用说不同城镇或地区了。或许,我们已经舍弃了对文化多样性的追求,开始追求更丰富的个人生活以及更丰富和快节奏的技术生活。
在难以分辨不同计算机图书的时代,Manning出版社以两个世纪前丰富多样的社区生活融入本书封面,以此来赞美计算机行业不断创新和敢为人先的精神。
本书由异步社区出品,社区(https://www.epubit.com)为您提供后续服务。
您还可以扫码右侧二维码, 关注【异步社区】微信公众号,回复“e61444”直接获取,同时可以获得异步社区15天VIP会员卡,近千本电子书免费畅读。
作者、译者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“发表勘误”,输入相关信息,单击“提交勘误”按钮即可,如下图所示。本书的作者和编辑会对您提交的信息进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区投稿(直接访问www.epubit.com/contribute即可)。
如果您所在的学校、培训机构或企业想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接通过邮件发送给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、人工智能、测试、前端、网络技术等。
异步社区
微信服务号
本书第一部分将介绍Kafka及其可能的应用场景。
第1章将详细描述为什么需要使用Kafka,并解开你可能听说过的一些关于Kafka和Hadoop的谜团。
第2章将重点讲述Kafka的高级架构,以及构成Kafka生态系统的其他各个部分—— Kafka Streams、Connect和ksqlDB。
在阅读完这一部分的内容后,你就可以准备开始向Kafka写入消息或从Kafka读取消息了。同时,也希望你掌握了一些关键术语。
本章内容:
● 使用Kafka的原因;
● 关于大数据和消息系统的常见疑问;
● 消息传递、流式处理和物联网数据处理的真实应用场景。
开发人员正置身于一个充满数据的世界,数据从四面八方涌来,以至于他们不得不面对这样一个事实:遗留系统可能已经不是前进路上的最佳选择。作为新的数据基础设施之一,Apache Kafka[1]已经占领了IT领地。Kafka正在改变数据平台的标准。它引领了从抽取、转换、加载(Extract Transform Load,ETL)和批处理工作流(通常在预定义的时间内批量处理任务)到近实时数据处理的转变(参见R. Moffatt的文章“The Changing Face of ETL”)。批处理曾经是企业数据处理的标准,但在看到Kafka提供的强大功能之后,企业可能不会再回头看它一眼了。事实上,除非出现了新的方法,否则你可能无法处理正在向各种规模的企业滚去的数据雪球。
因为数据太多,所以系统很容易过载。遗留系统处理数据的时间窗口可能要从某天晚上一直持续到第二天。为了跟上持续不断的数据流或不断变化的数据,及时处理它们是保持最新系统状态的一种方法。
Kafka顺应了当今IT领域的许多最新和最实用的趋势,让日常工作变得更加容易。例如,Kafka已经进入了微服务设计和物联网(Internet of Things,IoT)领域。作为众多公司的一项事实上的技术标准,Kafka不仅仅是为少数“极客”而准备的。在本书中,我们将从讲解Kafka的特性开始。除Kafka之外,我们还将更多地讲解现代流式处理平台的面貌。
[1] Apache、Apache Kafka和Kafka是Apache软件基金会的注册商标。
Kafka网站将Kafka定义成一种分布式流式处理平台。它有3个主要功能:
● 读写记录,就像读写一个消息队列那样;
● 存储记录,有一定的容错能力;
● 实时处理数据流(参见Apache Software Foundation网站上发布的“Introduction”)。
在日常工作中不怎么接触消息队列或Broker的读者在讨论此类系统的一般用途和工作流时可能需要一些帮助。为简单起见,我们可以把Kafka的核心部件类比成家庭娱乐系统的接收器。图1.1描绘了接收器和最终用户之间的数据流。
图1.1 接收器和最终用户之间的数据流
如图1.1所示,卫星、DVD和蓝光播放器连接到一个中央接收器。你可以想象这些设备会以某种已知的格式定时发送数据。在播放电影或CD时,几乎会持续地产生数据流。接收器将处理这些持续的数据流,并将其转换为可供另一端外部设备使用的格式(接收器将视频发送到电视上,将音频发送给解码器和扬声器)。那么这和Kafka有什么关系呢?在图1.2中,我们从Kafka的角度看待类似的关系。
图1.2 Kafka生产者和消费者之间的数据流
Kafka包含用于与其他系统发生交互的客户端。其中的一个客户端叫作生产者,它向Kafka Broker发送数据流。Broker充当了图1.1中接收器的角色。Kafka的另一个客户端叫作消费者,它从Broker读取和处理数据。数据的目的地不一定只有一个。生产者和消费者之间是完全解耦的,它们是独立运行的。我们将在后面的章节深入讲解这是如何做到的。
与其他消息平台一样,Kafka就像是(对于生产者)进入系统和(对于消费者或最终用户)离开系统的数据的中间人。消息的生产者和最终用户之间是分离的,因此可以实现松散的耦合。生产者可以发送任意的消息,但不知道是否有人订阅。此外,Kafka提供了适用于各种业务场景的消息传递方式。Kafka的消息至少可以采用以下3种传递方式(参见Apache Software Foundation网站)。
● 至少一次语义——在需要时发送消息,直到得到确认。
● 至多一次语义——只发送一次消息,如果失败,不重新发送。
● 精确一次语义——消息的消费者只能读取一次消息。
我们深入研究一下这些消息传递语义的含义。我们先看一下至少一次语义(见图1.3)。在这种情况下,Kafka允许消息的生产者多次发送相同的消息,并将其写入Broker。如果生产者没有收到消息写入Broker的确认,可以重新发送消息(参见 Apache Software Foundation网站)。对于那些不允许丢失消息的场景,如付款的场景,这是最安全的传递方式之一,尽管可能需要在消费者端做一些过滤。
图1.3 至少一次语义传递方式下的消息流
至多一次语义(见图 1.4)是指消息的生产者只发送一次消息,并且永远不进行重试。如果发送失败,生产者会继续发送其他消息,不再重新发送已经发送失败的消息(参见Apache Software Foundation网站)。为什么有人可以接受消息丢失呢?试想一下,如果一个很受欢迎的网站正在跟踪访问者的页面浏览情况,那么在每天发生的数百万个页面浏览事件中遗漏掉一些是可接受的。保持系统正常运行,不需要等待确认,可能比丢失数据更重要。
图1.4 至多一次语义传递方式下的消息流
Kafka在0.11.0版本中加入了精确一次语义(Exactly Once Semantics,EOS)。EOS在发布后引发了许多褒贬不一的讨论。EOS(见图 1.5)对于许多场景来说是很理想的语义。它似乎是对消息除重的一种逻辑上的保证,并让消息除重成为过去。但大多数开发人员认为在生产端发送消息并能够在消费端接收到同样的消息就已经足够了。
另一个关于EOS的讨论是,它是否有可能实现。虽然这将涉及更深入的计算机科学理论知识,但我们还有必要了解一下Kafka是如何定义EOS特性的(参见N. Narkhede的文章“Exactly-once Semantics Are Possible: Here’s How Apache Kafka Does It”)。即使生产者不止一次发送同一条消息,也只会把该消息发送给消费者一次。EOS在所有的Kafka层都有触点——生产者、主题、Broker和消费者——我们将在本书后面简要讨论。
图1.5 EOS传递方式下的消息流
除传递各种语义之外,Broker的另一个作用是,即使消费端的应用程序因为发生故障或处于维护期而关闭,生产者也不需要等待消费者处理消息。当消费者重新上线并继续处理数据时,它们能够从之前离开的位置继续,而不会丢失任何信息。
随着越来越多的传统公司开始面临数字化方面的挑战,一个很重要的问题摆在他们面前:他们将如何为未来做好准备?一个可能的答案是使用Kafka。Kafka是一个高性能的消息传递系统,默认提供复制和容错的特性。
Kafka可以满足生产环境中巨大的数据处理需求(参见N. Narkhede的文章“Apache Kafka Hits 1.1 Trillion Messages Per Day—Joins the 4 Comma Club”)。这一切都要归功于这个直到2017年才发布1.0版本的工具!除这些引人注目的事实之外,为什么用户要开始关注Kafka?接下来,我们一探究竟。
为什么软件开发人员会对Kafka感兴趣?Kafka的采用量呈“爆炸式”增长,但相关开发人员的需求未能得到满足。我们需要改变传统的数据处理思维方式。各种公开分享的经验或走过的弯路可以帮助开发人员了解为什么Kafka对于他们的数据架构来说是一个充满吸引力的工具。
对于Kafka开发新手来说,借助已知的东西来解决未知的问题是帮助他们进入这一领域的一种方式。例如,Java开发人员可以利用Spring的概念,如依赖注入。Spring for Apache Kafka(spring-Kafka)项目已经发布了几个主要版本。与Kafka相关的项目(包括Kafka本身)都有一个不断增长的工具生态系统。
作为普通的开发人员,大多数程序员可能遇到过耦合性问题。例如,你想要修改一个应用程序,但可能有许多其他应用程序与这个应用程序产生了耦合。或者,当你想要编写单元测试时,发现需要创建大量的Mock。在这些情况下,如果Kafka使用得当,就能助你一臂之力。
以一个员工用来提交带薪休假申请的人力资源系统为例。如果你熟悉CRUD(Create,Read,Update,Delete,创建、读取、更新和删除)风格的系统,你就应该知道,提交的休假申请很可能需要经过薪资系统和用于预测工作进度的项目管理系统的处理。那么,你会将这两个应用程序连接在一起吗?如果薪资系统崩溃了该怎么办?这会影响项目管理系统的可用性吗?
有了Kafka,我们可以将原先不得不捆绑在一起的应用程序解耦(第11章将更深入地探讨如何让数据模型变得更加成熟)。我们可以将Kafka放在工作流的中间位置(参见K. Waehner的文章“How to Build and Deploy Scalable Machine Learning in Production with Apache Kafka”),数据接口就变成了Kafka,而不是无数个API(Application Program Interface,应用程序接口)和数据库。
有人说有其他更好、更简单的解决方案。例如,用ETL将数据加载到每个应用程序的数据库里,这样每个应用程序就只需要一个接口,很简单,对吧?但是,如果原始数据源出现损坏或数据过时了该怎么办?你可以多久更新一次?可以容忍何种程度的延迟或不一致?这些数据副本是否会过时或与数据源偏移太大,以至于再次运行相同的流程很难得到相同的结果?真正的原因是什么?Kafka可以帮助避免这些问题。
另一个有可能提升Kafka使用可信度的因素是Kafka也用到了自己的很多特性。例如,在第5章深入介绍消费者时,我们将看到Kafka如何在内部使用主题来管理消费者偏移量。在0.11版本发布之后,Kafka使用内部主题来实现精确一次语义。Kafka允许多个消费者读取同一条消息,产生多种可能的结果。
开发人员想问的另一个问题可能是,为什么不跳过Kafka的核心内容,直接学习Kafka Streams、ksqlDB、Spark Streaming或其他平台。有无数个应用程序正在使用Kafka,抽象层固然好(有时候确实需要这么多活动组件),但我们相信Kafka本身也是值得学习的。
只知道Kafka是Flume的一个可选组件与深入了解Kafka所有配置选项的含义,是有区别的。尽管Kafka Streams可以简化你将在本书中看到的示例,但在Kafka Streams出现之前,Kafka就已经非常成功了。了解Kafka的基础是必不可少的一步,希望它能够帮助你了解为什么一些应用程序会使用它,以及它的内部原理。如果你想成为流式处理领域的专家,就很有必要了解应用程序底层的分布式组件以及所有可用来调优应用程序的方法。从纯技术的角度来看,许多令人兴奋的计算机科学技术应用在Kafka中。人们讨论最多的可能是分布式提交日志(第2章将深入介绍它)和层级时间轮(参见Y. Matsuda的文章“Apache Kafka, Purgatory, and Hierarchical Timing Wheels”)。这些例子都展示了Kafka如何通过应用有趣的数据结构解决实际的可伸缩性问题。
因为Kafka是开源的,所以我们可以深入挖掘源代码,通过在互联网上搜索获得文档和示例。我们可获得的资源并不局限于在特定工作场所内传播的知识。
通常,当高层的管理人员听到Kafka这个单词时,他们可能更多地对这个名字感到疑惑,而并不关心它可以用来做什么。所以,你最好解释一下这个产品的价值。此外,最好从更高和更大的角度考虑这个工具真正的附加价值是什么。
Kafka的一个重要特性是它可以获取海量数据,并使数据可供各个业务领域使用。这种为所有业务领域提供信息可用性的能力提高了企业的灵活性和开放性。没有什么是预先设定好的,但提升对数据的可访问性是一个潜在的结果。大多数高层的管理人员还知道,随着越来越多的数据涌入,企业希望能够尽快获得结论。与其让数据在磁盘上持续存放并丧失价值,不如在数据到达时就获取它们的价值。批处理作业限制了转化数据价值的速度,而使用Kafka是一种可以摆脱批处理作业的方法。快数据(fast data)似乎成了一个新名词,它暗示真正的数据价值与大数据本身的承诺有所不同。
对于许多企业开发团队来说,在Java虚拟机(Java Vitual Machine,JVM)上运行应用程序是他们非常熟悉的场景。对于一些需要在本地监控数据的企业来说,在本地运行应用程序是一个关键驱动因素。当然,云计算和托管平台也是不错的选择。Kafka可以水平扩展,而不仅限于垂直扩展(垂直扩展最终会触及天花板)。
也许学习Kafka最重要的原因之一是看看初创公司和其他行业的公司如何降低曾经令人望而却步的算力成本。分布式应用程序和架构不再依赖可能价值数百万美元的大型服务器或大型机,而以更少的财务支出向竞争对手快速逼近。
在开始学习新技术时,人们通常会尝试将现有的知识与新的概念关联起来。虽然我们也可以用这个技巧来学习Kafka,但我们更想要指出的是到目前为止我们在工作中遇到的一些常见的误解。我们将在下面的几节中介绍它们。
如前所述,Kafka是一个强大的工具,经常用在各种场景中。然而,它似乎是因为用在Hadoop生态系统中才广受关注的,而且可能因为作为Cloudera或Hortonworks平台工具的一部分才被用户熟知。Kafka只能与Hadoop一起使用是一个常见的疑问。那么是什么导致了这个谜团?其中一个原因是很多工具将Kafka作为其产品的一部分。Spark Streaming和Flume就是这方面的例子,它们正在使用(或曾经使用过)Kafka。ZooKeeper是Hadoop集群的一个常见组件,也是Kafka的依赖项(取决于Kafka的版本),所以这可能进一步加剧了这个谜团。
另一个常见的谜团是Kafka依赖Hadoop分布式文件系统(Hadoop Distributed File System,HDFS),但事实并非如此。等我们深入了解Kafka的工作原理后,我们就会发现,如果中间有NodeManager,Kafka处理事件的速度会慢得多。同样,Kafka块复制(通常也是HDFS的一部分)的实现方式也与HDFS不一样。例如,Kafka副本默认情况下是不进行恢复的。这两个产品以不同的方式实现复制,因为Kafka的持久化特性,很容易就被与Hadoop归为一类(Hadoop默认情况下预期会发生故障,因此需要规划故障恢复),而且Hadoop和Kafka之间的整体目标有相似的地方。
另一个谜团是,Kafka只是另一种消息系统。直接将各种工具(例如,Pivotal的RabbitMQ或IBM的MQSeries)的特性与Kafka的特性进行对比常常要带上星号(或小字说明),这种对比并不公平,因为每种工具都有各自最佳的应用场景。随着时间的推移,一些工具已经或将会加入新的特性,例如,Kafka增加了精确一次语义。我们可以通过修改默认配置让它们的功能与同类工具接近。一般来说,下面是我们将要深入探讨的两个相对突出且值得关注的特性:
● 重放消息的能力;
● 并行处理数据的能力。
Kafka可以支持多个消费者。也就是说,从Broker读取消息的应用程序不影响其他同样读取这些消息的应用程序。这种设计的一个结果是,已经读取了一条消息的消费者可以选择再次读取这条消息(和其他消息)。在一些架构(如第8章将介绍的Lambda架构)模型中,程序员的人为错误与硬件故障一样,都是不可避免的。假设你正在读取数百万条消息,但忘记处理原始消息中的某个字段。在一些队列系统中,消息可能已经删除,或者发送给副本,抑或重放队列。而Kafka为消费者提供了在主题上查找特定位置并从这里重新读取消息的功能(存在一定程度的限制)。
我们已经简单地提到过,Kafka支持数据并行处理,并且同一个主题可以有多个消费者。Kafka有消费者组的概念(参见第5章)。消费者组的成员关系决定了哪些消费者可以读取哪些消息,以及成员消费者已经读取了哪些消息。每个消费者组与其他消费者组是相互独立的,多个应用程序可以按照自己的节奏使用多个消费者读取消息。读取消息有多种方式:可以由一个应用程序中的多个消费者读取,也可以由多个应用程序读取。不管其他消息系统提供了什么功能,我们都要看一下那些让Kafka成为开发人员必备之选的应用场景。
帮助读者将Kafka应用到实际当中是本书的核心目标。关于Kafka,我们很难说它在某一方面做得特别好,但它在许多特定的应用场景下表现得很出色。虽然我们需要先掌握一些基本的概念,但是如果能从高层次介绍Kafka在现实世界中的一些应用场景可能会很有帮助。Kafka的官方网站列出了Kafka在现实世界中的一些应用场景。
一些用户在第一次使用Kafka时把它作为一个消息系统。在使用其他消息系统(如IBM WebSphere MQ,也就是原来的MQSeries)多年之后,使用Kafka(当时的版本是0.8.3)似乎就是简单地将消息从A点移动到B点。Kafka放弃使用流行的协议和标准,如可扩展通信和呈现协议(Extensible Messaging and Presence Protocol,XMPP)、Java消息服务(Java Message Service,JMS)API(现在是Jakarta EE的一部分)或OASIS高级消息队列协议(Advanced Message Queuing Protocol,AMQP),而开发了自己的二进制TCP。稍后我们将深入讲解一些复杂的应用场景。
对于使用Kafka客户端开发应用程序的用户来说,大部分东西与配置有关,逻辑也相对简单(例如,“我想向这个主题发送一条消息”)。使用Kafka的另一个原因是把它作为一个发送消息的持久性通道。
通常情况下,在内存中保存数据不足以起到保护数据的作用,如果服务器重启,数据就丢失了。Kafka从一开始就支持高可用性和持久存储。Flume有一个Kafka通道,Kafka的复制特性和高可用性让Flume事件在代理(或运行它的服务器)发生崩溃时仍然对其他接收器可用(参见Apache Software Foundation网站上的文章“Flume 1.9.0 User Guide”)。Kafka可用于构建健壮的应用程序,并帮助分布式应用程序处理在某些时候必然会发生的预期故障。
日志聚合(见图1.6)在很多情况下很有用,包括收集在分布式应用程序中发生的事件。从图1.6中可以看到,日志文件作为消息发送给Kafka,然后不同的应用程序从各自的逻辑主题上消费这些消息。凭借处理海量数据的能力,从不同的服务器或事件源收集事件成了Kafka的一个关键特性。一些组织根据日志事件的内容将它们用在审计和故障趋势检测中。Kafka也用在各种日志系统中(或作为输入工具)。
既然需要处理这么多的日志文件,那么Kafka是如何在不导致服务器资源耗尽的情况下保持性能的?消息吞吐量有时候会让系统不堪重负,因为处理每条消息都需要时间和开销。Kafka使用消息批次来发送数据和写入数据。Kafka通过追加的方式写入日志,这比随机访问文件系统具有更高的性能。
图1.6 日志聚合
在过去,微服务一般使用REST之类的API作为通信手段,但现在它们也可以使用Kafka在异步服务之间通过事件来通信(参见B. Stopford的文章“Building a Microservices Ecosystem with Kafka Streams and KSQL”)。微服务可以使用Kafka而不是特定的API作为它们的交互接口。Kafka已经将自己定位成帮助开发者快速获取数据的基础组件。尽管Kafka Streams现在可能是许多开发人员在开始一个新项目时的默认选择,但是早在2016年Streams API发布之前,Kafka就已经将自己确立为一个成功的解决方案。Streams API可以被视为一个构建在生产者和消费者之上的抽象层。这个抽象层就是一个客户端库,提供了处理无限定事件流的高级视图。
Kafka 0.11引入了精确一次语义。等稍后读者对Kafka有了更深入的了解,我们将讨论精确一次语义在现实当中的意义。不管怎样,使用Streams API实现端到端工作负载的用户都可以获得Kafka提供的消息传递保证。Streams让用户可以在不实现任何自定义应用程序逻辑的情况下更容易确保消息从事务开始到结束只处理一次。
物联网设备(见图 1.7)的数量只会随着时间的推移而增加。这些设备时刻在发送消息,特别是当它们连接到Wi-Fi或蜂窝网络时,发送的消息会突然激增,所以我们需要一些东西来高效地处理这些数据。处理海量数据正是Kafka的强项之一。正如我们之前所说的,处理这些消息对于Kafka来说不是问题。信标、汽车、电话等都会发送数据,我们需要一些东西来处理这些数据,并基于处理结果执行一些操作(参见Confluent文档“Real-Time IoT Data Solution with Confluent”)。
这些只是Kafka著名应用场景的一小部分,Kafka还有许多实际的应用场景。后面即将讲解到的有关Kafka的基础概念对于实现更多的应用场景来说至关重要。
图1.7 物联网设备
尽管Kafka已经用在一些有趣的场景中,但是它并不一定总是完成工作的最佳工具。下面是一些更适合使用其他工具或代码的场景。
有时候,你可能只需要月度或年度汇总数据。我们假设你不需要按需查询,也不需要快速获得答案,甚至不需要重新处理数据。在这些情况下,你可能不需要为了完成这些任务而全年运行Kafka(如果数据量是可管理的,可以考虑批处理)。通常,不同用户对批次大小的阈值定义是不同的。
如果你的主要数据访问模式是随机查找,那么Kafka可能不是最好的选择。Kafka擅长线性读写,因为这样可以尽可能快地移动数据。你可能听说过Kafka有索引文件,但它们与关系数据库的字段和主键索引不同。
类似地,如果你要求Kafka某个主题的消息保持准确的顺序,就要看一下你的工作负载是怎样的。为了避免消息乱序,需要确保最多只有一个生产者,同时,主题只能有一个分区。解决方案有很多,但如果你有大量需要保持严格顺序的数据,可能会出现一些潜在的问题,因为这个时候一个消费者组里只有一个消费者可以读取数据。
另一个实际的问题是如何处理体量很大的消息。Kafka的默认消息大小为1MB(参见Apache Software Foundation网站)。较大的消息会给内存带来压力。换句话说,你需要注意页面缓存可以保存多少条消息。如果你打算发送大量的存档,最好看一下是否有更好的方法来管理这些消息。请记住,对于这些情况,尽管你可能可以用Kafka实现你的最终目标(确实有可能),但是它可能不是首选方案。
Kafka社区提供了非常好的文档。Kafka已经是Apache的一部分(2012年从孵化器毕业),它的文档就放在Apache Kafka网站上。
Confluent是另一个很好的信息资源。Confluent由Kafka原始作者创立,它积极地影响着Kafka未来的发展。Kafka原始作者还为企业提供特定的功能和支持,帮助企业开发自己的流式处理平台。他们的工作也有助于Kafka的开源,他们甚至还组织讨论如何面对生产环境中的挑战和如何取得成功的讲座。
在开始深入了解更多的API和配置选项之前,如果你需要知道更多的细节,可以参考这些资源。在第2章中,我们将发现更多的细节,我们将使用特定的术语,并开始以一种更实际的方式了解Kafka。
● Kafka是一个流式平台,可以用它来快速处理大量的事件。
● Kafka可以作为消息总线使用,但此时需要忽略它提供的实时处理数据的能力。
● 在过去,人们把Kafka与其他大数据解决方案联系在一起,但Kafka本身也提供了一个具有可伸缩性和持久性的系统。Kafka也使用了容错和分布式技术,并通过自己的集群能力满足了现代数据基础设施的核心需求。
● Kafka可以快速处理海量事件流,如物联网数据。随着应用程序数据不断增长,Kafka为曾经只能离线批处理的数据提供快速的处理结果。
读者服务:
微信扫码关注【异步社区】微信公众号,回复“e61444”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。