Kafka都没整明白,还敢去面试?
Apache Kafka 被誉为时下热门的企业级消息传递系统,其初衷是一个分布式流系统,用于发布和订阅记录流,以其快速,高可扩展性以及较完美的容错效果备受业内人士青睐。
放眼当下数据为王的时代,深入了解 Apache Kafka 及其常见的部署应用,快速实现数据架构(Kafka Fast Data Architecture)已是大势所趋,刻不容缓。
以下分别 Kafka 架构,四大核心 API,典型应用场景,Kafka 代理与消息主题,集群的创建,流 APIs(Stream APIs)及其处理模式等不同方面展开详细介绍。
Kafka:分布式流平台
Kafka 是一个分布式流平台,用于发布和订阅消息流(也称记录流或数据流),快速有效地利用 I/O 进行数据流的批处理,压缩及解耦,并将数据流传输到数据池,应用程序和实时流分析系统中。Kafka 将主题消息分区复制到多个服务器中,允许用户通过自己的应用程序来处理这些记录。
Kafka 四大核心 APIs
Kafka 由记录(records),主题(topics),使用者(consumers),生产者(producers),代理服务(brokers),日志(logs),分区(partitions)和集群(clusters)组成。Kafka 主题是一个记录流,每个主题都有对应的日志,该日志是该主题在磁盘上的存储,每个主题日志又分为多个分区和片段。
Kafka Producer API 用于生成数据记录流。Kafka Consumer API 用于消费来自 Kafka 的记录流。
Broker 是在 Kafka 集群中运行的 Kafka 服务器,Kafka 集群由多个代理服务器组成。
生产者 API(Producer API):消息的生产者,向 Kafka broker 发消息的客户端。
允许客户端与集群中运行着的 Kafka 服务器相连接,并将记录流发布到一个或多个 Kafka topics(消息主题)中。
一台 Kafka 服务器就是一个 broker,一个集群由多个 broker 组成,一个 broker 可以容纳多个 topic。
消费者 API(Consumer API):消息消费者,向 Kafka broker 获取消息的客户端。
允许客户端连接集群中运行着的 Kafka 服务器,并消费其中一个或多个 Kafka topics(消息主题)的记录流。
流 API(Stream API):充当流处理器,用于输入输出流的转换。
允许客户端充当流处理器,从一个或多个 topics(消息主题)消费输入流,并生产输出流,输出到一个或多个其他 topics(消息主题)中,从而有效地将输入流转换至输出流。
连接器 API(Connector API):允许编写可重用的生产者和消费者代码。
我们可以从任何关系型数据库中读取数据,并将其发布到主题中,同时也可以“消费”这个主题中的数据,并将其写入关系型数据库。
由此可见,Connector API 支持构建和运行可重复使用的生产者或消费者,并将 topic 连接到现有的应用程序或数据系统。(例如,就关系型数据库而言,其连接器可以捕获到各个表中的每个变化。)
Kafka应用场景
消息系统
Kafka 作为企业消息传递系统,通过源系统及目标系统间的分离来实现数据交换。与 JMS 相比,Kafka 兼具高吞吐量分区及高可靠容错力的复制功能。Web 站点活动跟踪
跟踪记录用户在网站上的所有事件信息,从而进行数据的分析及脱机处理。日志汇总
用于处理来自不同系统的日志,尤其是那些处于微服务架构分布式环境中的系统,这类系统通常部署在不同的主机上,因此 Kafka 需要汇总来自不同系统的各类日志,进而对这些日志集中进行分析处理。指标收集
Kafka 可用于收集来自各类系统/网络的指标,并进行监控,Kafka 配有专门的指标报告生成工具,如 Ganglia,Graphite 等。Kafka Brokers & Kafka Topics
Kafka Broker(代理服务器)
Kafka 集群中的一个实例称之为代理(服务器),在 Kafka 集群中,只要连接其中任意一个代理(服务器)就能访问到整个集群,每个代理在集群中通过 ID 进行标识。Kafka Topics(消息主题)
一个消息主题(Topic)是一个消息记录发布后的逻辑名称,在 Kafka 中,Topic 被分为若干个分区(Partitions),用于消息的发布。这些分区分布在集群的各个代理服务器(Brokers)中,为了实现可扩展性,通常将一个非常大的 Topic 分布在多个代理服务器(Broker)上。
由于一个 Topic 可以分为多个分区(Partition),每个分区(Partition)都是一个有序的队列。
分区(Partition)中的每条消息都会被分配一个有序的 ID(即偏移量,Offset)。
如下图所示,假设当前有一个主题(Topic),该主题(Topic)有三个分区,集群中有三个代理(Broker),则每个代理都有一个分区。要发布到分区的数据以偏移量(Offset)增量的方式追加。
其中“Offset”即偏移量,Kafka 的存储文件都是按照“offset.kafka”来命名,用 Offset 方式命名是为了便于查找,如果想找位于 2046 的位置,只需找到 2045.kafka 的文件即可。
以下是分区(Partitions)使用时值得注意的要点:
- 每个消息主题(Topic)按名称标识,集群中允许有多个已命名的消息主题。
- 每个消息前后顺序的有效性仅限于当前分区级别(maintained at the partition level),而非跨主题。
- 数据一旦写入分区,则不会被覆盖,这就是Kafka中强调的数据不变性(immutability)
- 分区中的消息通过键(key),值(values),时间戳(timestamps)的形式一起存储,Kafka 确保每一个给定密钥的消息都会发布到同一个分区中。
- 在 Kafka 集群中,每一个分区都有一个引导程序(leader),该引导程序负责对该分区执行读/写操作。
上图是一个例子,当前集群中仅一个消息主题(Topic),该主题包含三个分区(partition0,partition1,partition2),集群中有三个代理服务器(broker1,broker2,broker3)。
当前每个分区的副本都复制到另外两个代理服务器(Broker)中,即每个代理服务器(Broker)上包含了三个分区。
因此即便其中某两个代理服务器(Broker)发生故障,也不用担心数据会丢失。
如上,当我们在 Kafka 中创建主题时,始终建议确保主题(Topic)的复制因子大于 1,并且小于/等于集群中的代理服务器(Broker)数量,这是非常推荐的做法。
上图示例中,当前主题的复制因子为 3(即,一份原始数据,两份副本数据), 不难推算出每个分区的引导程序加上其副本数量总共为“3”。
该示例中,每个分区都有一个引导程序(称之为“leader”),以及其他两个同步副本(称之为“follower”)。
对于分区 partition 0 来说,broker1 是“leader”, broker2 和 broker3 都是“follower”,从而分区 partition 0 的所有读写操作都将在 broker1 中进行。
同时,之后更新的内容也会被同步复制到 broker2 和 broker3 对应的分区(partition)中。
创建 Kafka 集群——Demo
我们还是以上图中三个 Broker 组成的 Kafka 集群为例,拆解 Kafka 集群创建的步骤。Kafka 集群环境准备
首先需要准备好一台安装有 Zookeeper 的机器,没有 Zookeeper,Kafka 集群将无法工作。同时建议直接从官网下载最新版本的 Apache Kafka,目前版本更新至2.11,直接解压后将其放置到 bin 目录下:
https://archive.apache.org/dis ... 0.tgz
然后启动 ZooKeeper,为什么需要 Zookeeper?它在这里主要负责协调服务,管理代理服务 Broker,确定每个分区中的引导程序,以及在 Kafka 消息主题或代理服务发生变更时及时发出警告。
通过以下命令可以启动一个Zookeeper实例:
启动 Kafka Brokers
成功安装 Kafka 并启动 ZooKeeper 实例后,接下来就可以开启 Kafka Broker 了,这里共启动了三个 Kafka Broker。具体启动方式:先定位到 Kafka 根目录下的“config”文件夹下,找到“server.properties”文件,将其复制三次。
然后分别命名为server_1.properties,server_2.properties 以及 server_3.properties,并针对三个文件内容做如下编辑,直接保存即可:
保存后通过命令开启这三个代理服务:
创建主题
通过如下命令创建消息主题:生成引导服务
通过 Kafka 控制台生成器(Kafka console)指定任意一个代理服务地址,并基于之前创建的主题发布一些消息。这个指定的代理服务就被视作为引导服务程序,用于访问整个集群。
“消费”消息
通过 Kafka 控制台来使用消息,用户(即:消息消费者)需要指定任意一个代理服务(Broker)地址作为引导服务器。在阅读消息时,用户(即:消息消费者)是看不到消息顺序的,上文中也提到过消息的先后顺序仅在分区级别(partition level)进行维护,而非主题级别(topic level)。
通过以下命令可以描述主题并查看各分区的分布情况,以及每个分区的引导服务器:
从上面的执行结果可以看出:
- broker-1 是分区 0 的引导服务器。
- broker-2 是分区 1 的引导服务器。
- broker-3 是分区 2 的引导服务器。
- broker-1,broker-2,broker-3 分别具有每个分区的副本(同步且相互备份)。
Kafka Streams API
Kafka 常被用作将流数据实时传输到其他系统中,此时 Kafka 作为中间层,主要用来解耦分离实时数据管道。Kafka 流是 Kafka 生态系统的一部分,它提供了实时分析的功能,支持将流数据传输到大数据平台或 RDBMS,Cassandra,Spark 中,以进行将来的数据分析。
Kafka Stream API 简单易用,通过其强大的技术能力可处理所有存储于其中的数据,同时该 API 也为我们提供了一套 Kafka 标准类的实现规则。
在实际工作中为了能够创建支持核心业务的实时应用程序,我们需要 Kafka Stream API 的大力协助。
Kafka Stream API 独特之处在于,通过其构建的应用程序都是普通应用程序。
所以这些应用程序可以像其他任何应用程序一样,进行打包,部署和监控,而无需单独安装专门的处理集群或类似基础架构,这些额外部署的基础架构往往比较耗钱。
流(Stream)是 Kafka Streams 提供的最重要的抽象对象,代表了无限且持续更新的数据集。
流是一系列不可变数据记录的序列,具备有序,可重复,容错等特性,我们可以简单将其视为记录流(定义为:KStream)或变更日志流(定位为:KTable 或 GlobelKTable)。
流处理器(Stream Processor)是处理器拓扑结构中的一个节点,包含应用于流数据的处理逻辑,一系列节点组成了拓扑结构中的处理步骤(用于转换数据)。
Kafka Streams API 处理数据——Demo
Kafka Stream API 为实现流数据处理,即消息在 Kafka 中的消费及回写,提供了两种选项:- 高级 Kafka Streams DSL(high-level DSL)。
- 低级处理器 API:用于数据基本处理,组合处理,本地状态存储。
高级 DSL(high-level DSL)
高级 DSL 由记录流(KStream) 和日志流(KTable/GlobalKTable)两大主要抽象类别组成,包含一系列已实现的方法可供调用。KStream 是记录流的抽象,其中每个数据都是无限数据集中的简单键值,KStream 提供了多种处理数据流的功能。
例如:map,mapValue,flatMap,flatMapValues,filter;同时还支持多个流连接,流数据的聚合。
KTable 是变更日志流的抽象,在变更日志中,对具有相同键的行(row)进行覆盖,因而每条数据记录都被视作为插入或更新。
处理器 API(lower-level processor )
低级处理器 API 通过扩展抽象类(AbstractProcessor),覆盖含有业务逻辑的处理方法,从而实现客户端流数据的访问,允许基于输入数据流执行相应的业务逻辑,同时将其结果作为下游数据转发至客户端。相较于高级 DSL 提供具有功能样式的即用型方法,低级处理器API则按需提供处理逻辑。
Kafka Stream API 应用——高级 DSL Demo
前提:必须在当前环境中有以下依赖,版本视当前情况而定。导入以下包:
Kafka 配置属性:
实例化 KStreamBuilder,创建一个 KStream 对象:
KStreamBuilder 有个 Stream 方法,该方法以主题名称(topic name)作为参数,返回一个 KStream 对象,即,订阅了指定主题的实例化对象。
基于 KStream 对象,这时我们就可以使用 Kafka Streams 高级 DSL 提供的众多方法(例如:map,process,transform,join 等),然后将处理后的数据发送到另一个主题。
最后,通过构建器(builder)和流配置进行流式传输:
通过 Kafka Streams API,我们无需单独部署集群即可在 Kafka 中进行数据流处理。
Kafka Streams API 给我们带来的便捷主要包含以下几个方面:
- 高可扩展性,灵活性,分布式和容错性。
- 支持有状态和无状态处理。
- 具有窗口,联接和聚合的事件时间处理。
- 通过 Kafka Streams DSL 或较低级别的处理器 API 使用已经定义的常见转换操作。
- 对处理没有单独的群集要求(与 Kafka 集成)。
- 采用一次一个记录的处理以实现毫秒级的处理延迟。
- 支持 Kafka Connect 连接到不同的应用程序和数据库。
总结
Kafka 的便捷操作是其备受业内人士广泛关注的原因之一,然而更重要的是其出色的稳定性,可靠性及耐用性,且具有灵活的发布/队列,可以很好地适应 N 个消费者组,具有强大的可复制性,可以为生产者提供一致性保证。本次分享基于 Kafka 核心要素及其常见部署做了详情解析,希望给圈内感兴趣的人士提供技术普及,交流互补。
作者:罗小罗,英国 TOP10 计算机专业,计算机科学与技术硕士,先后就职于汇丰,JPMorgan,HP,交行,阿里等国内外知名企业。涉及项目领域主要有:互联网金融,电商,教育,医疗等。现任就职于某世界 500 强公司,担任测试开发团队负责人,带领团队构建并持续优化自动化测试框架,研发自动化测试辅助类工具;擅长领域:单元/接口/性能/安全/自动化测试/CD/CI/DevOps;个人持续研究领域:自动化测试模型/数据分析/算法/机器学习等。
原文链接:https://mp.weixin.qq.com/s/oqfxAzZgccBqK0_4NQHmhQ