【51CTO.com原创稿件】Apache Kafka 被誉为时下热门的企业级消息传递系统,其初衷是一个分布式流系统,用于发布和订阅记录流,以其快速,高可扩展性以及较完美的容错效果备受业内人士青睐。
图片来自 Pexels
放眼当下数据为王的时代,深入了解 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/dist/kafka/1.0.0/kafka_2.11-1.0.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;个人持续研究领域:自动化测试模型/数据分析/算法/机器学习等。
编辑:陶家龙
征稿:有投稿、寻求报道意向技术人请联络 editor@51cto.com
【51CTO原创稿件,合作站点转载请注明原文作者和出处为51CTO.com】