Kafka 架构、核心机制和场景解读

摘要

Kafka 是一款非常优秀的开源消息引擎,以消息吞吐量高、可动态扩容、可持久化存储、高可用的特性,以及完善的文档和社区支持成为目前最流行的消息队列中间件。

Kafka 的开发社区一直非常活跃,在消息引擎的领域取的不俗成绩之后,不断拓展自己的领域,在基于事件的流处理平台方向一直发力,不断自我更新迭代力图成为这个领域内的事实标准。

Kafka 的消息引擎功能十分强大,但是一直没有停下自我突破的脚步,随着 3.0 版本的中 KRaft 协议的推出,Zookeeper 的退出进程正式启动,Kafka 开始了又一次的自我蜕变。

ZK 的移除是一个非常大胆的举动,因为 ZK 在 Kafka 的集群管理中居于核心的地位,不会轻易取代,那为什么 Kafka 选择了自行实现选举机制的路线?

此外,虽然 Kafka 具备诸多优秀的特性,这些如今被视为最佳实践的特性也是不断演化而来的,从其不断升级改进的过程中也能间接反映出生产环境所面临的现实问题,那么 Kafka 在实际的生产环境中的表现究竟如何?

作为业务方,使用 Kafka 作为消息中间件进行业务开发,保证服务平稳运行需要避开哪些雷区?

这篇文档将从一个比较高的视角,从 Kafka 的设计理念、架构到实现层面进行深入解读,随着对 Kafka 相关机制的深入了解,这些问题的答案将浮出水面。

须知事项

  • 这篇文档基于 Kafka 最近刚刚发布的 3.2 版本源码为基础进行介绍,主要讨论 Java 和 Scala 语言实现的原版客户端和服务端,其他语言版本的客户端与这篇文档介绍的机制在实现上会有较大出入,需要留意

  • 此外,字节的业务很多使用的都是自研的 BMQ [3],在客户端协议上是完全兼容的,但是服务端进行了完全的重构,本文介绍的相关服务端机制并不适用

  • Kafka 整个项目包括 Core、Connect、Streams,只有 Core 这一部分是我们通常说的核心消息引擎组件,另外两个都是基于这个核心实现的上层应用,这篇文章主要介绍的就是 Kafka Core 相关的内容,下面的 「Kafka 的应用架构部分」会对这一点做简要介绍

名词对照

下面的表格给出了 Kafka 中出现的一些高频和重要概念的对照解释

英文名

中文名

解释

备注

KIP

Kafka 改进提案

KIP(Kafka Improvement Proposal)是针对 Kafka 的一些重大功能变更的提案,通常包括改进动机、提议的改进内容、接口变更等内容

Partition

分区

一个独立不可再分割的消息队列,分区中会有多个副                                 本保存消息,他们的状态应该是一致的

Kafka 分区副本的同步机制不是纯异步的,有高水位机制去跟踪从副本的同步进度,并且有对应的领导者副本选举机制保证分区整体对外可见的消息都是已提交的

Replica

副本

分区中消息的物理存储单元,通常对应磁盘上的一个日志目录,目录中会对消息文件进一步进行分段保存

Leader Replica

主副本、领导者副本

指一个 Partition 的多个副本中,对外提供读写服务的那个副本

Kafka 集群范围有对等地位的组件是 Controller

Consumer

消费者

Kafka 客户端消费侧的一个角色,负责将 Broker 中的消息拉取到客户端本地进行处理,还可以使用 Kafka 提供的消费者组管理机制进行消费进度的跟踪

Consumer Group Leader

消费者组领导者

通常指 Consumer Group 中负责生成分区分配方案的 Consumer

这个概念非常容易和上面的 Leader Replica 混淆

Log start offset

消息起始偏移

Log start offset,Kafka 分区消息可见性的起点

此位置对应一条消息,对外可见可以消费

LSO

上次稳定偏移

Last stable offset,和 Kafka 事务相关的一个偏移

当消费端的参数isolation.level 设置为“read_committed"的时候,那么消费者就会忽略事务未提交的消息,既只能消费到LSO(LastStableOffset)的位置

LEO

消息终止偏移

Log end offset,Kafka 分区消息的终点

LEO 是下一条消息将要写入的位置,对外不可见不可供消费

HW

高水位

High water mark,用于控制消息可见性,HW 以下的消息对外可见

HW 的位置可能对应一条消息,但是对外不可见不可以消费,HW 的最大值是 LEO

LW

低水位

Low water mark,用于控制消息可见性,LW 及以上的消息对外可见

一般情况下和 Log start offset 可以等价替换,代码里也是这个逻辑

ISR

已同步副本

In sync replica 指满足副本同步要求的副本集合,包括领导者副本

副本同步是按照时间差进行判定的,而非消息偏移的延迟

Kafka 的应用生态

下面这张是我根据 Confluent 博客的一张资料图重绘的 Kafka 应用生态架构图,在正式开始介绍本文的主题之前,我们先了解一下 Kafka 的整个应用生态

​这张图中居于核心地位的是 Kafka Core 的集群,也是我们常用的消息引擎的这部分功能,是我们这篇文档重点介绍的对象

在核心的周围,第一层是 Producer 和 Consumer 的基础 API,提供基础事件流消息的推送和消费

而基于这些基础 API Kafka 提供了更加高级的 Connect API,能够实现 Kafka 和其他数据系统的连接,比如消息数据自动推送到 MySQL 数据库或者将 RPC 请求转换为事件流消息进行推送

此外,Kafka 基于自己的消息引擎打造了一个流式计算平台 Streams,提供流式的计算和存储一体化的服务

Kafka Core 架构

Kafka Core 架构部分的解读从模型、角色和实体、典型架构三个方向层层递进进行介绍

消息模型

Kafka 的消息模型主要由生产消费模型、角色和实体,以及实体关系构成,前者表示了消息的生产消费模式,后者描述了为了实现前者,其内部角色和实体存在怎样的逻辑关系

基本消息生产消费模型如下图所示:

图中展示了一个非常基本的生产消费场景,生产端向队列尾部发送消息,消费端从队列头部开始消费

从左往右看分别是消费端、消息队列、生产端,这三块我们分开进行详细介绍

消费端

在消费端有众多消费者,它们之间用消费者组关联起来

注意图中 Consumer 0 是没有分配到分区进行消费的,因为消费者组主要起个负载均衡的作用,一个分区被两个消费者消费从业务视角来看就是在重复消费了

对已经分配到分区的消费者来说,消费从队列的头部开始,在 HW 前结束

消息队列

消息队列处于整个消息模型中心的地位,是连接生产端和消费端的枢纽,Kafka 在性能优化上做的工作最多的就是这一个部分

因为 Kafka 的消息存储是队列的数据结构,只允许消息追加写入,这样的设计能最大化利用现有持久化存储介质的写入性能(SSD 和 HDD 都存在顺序写入性能远大于随机写入的特性),实现消息队列的高吞吐量

此外,Kafka 的队列还设计了高水位机制,避免未被从副本完成同步的消息被消费者感知并消费

生产端

生产端的 Producer 持续发送消息到队列中,消息追加到队列尾部,通过指定分区算法可以决定消息发往 Topic 下的哪个分区

小结

Kafka 的整个消息模型还是基于经典的消息模型去设计和改进的,消息模型的设计还是非常简洁易懂的,它的创新和优势就是在于将这一套模型用分布式的多机模式实现出来,能支撑住大并发、高吞吐量场景下的低时延、高可用的业务需求

当然这套模型之下,还有一些比较小的话题值得去讨论,我这里选了两个话题展开叙述来结束这一节

Push vs Pull

在 Kafka 定义的消息模型中,消费端是通过主动拉取消息的方式来消费的,但是与之对应的还有消息推送模型,Broker 对生产者推送过来的消息进行主动分发和推送到消费端

直觉上我们会觉得这种方式很自然,或者认为这是消息引擎的唯一范式,但是实际上关于为什么选择 Pull 的方式来进行消费,Kafka 的官方文档中关于这部分设计有专门列出来,主要讨论的点是消息消费的流控策略应该放在 Broker 端还是 Consumer 端。

零拷贝(Zero-Copy)

零拷贝从广义的角度来看不是一种具体的技术实现(仅指操作系统实现的零拷贝机制),而是一种优化思想或者技巧,针对程序运行中不可变的数据或者不可变的部分尽量减少或者取消内存数据的拷贝,用内存地址去引用这些数据

Kafka 的消息队列的核心功能就是进行各种数据的 IO 和转发(IO 密集型应用),零拷贝带来的收益非常明显:

  • 减少了 JVM 堆内存占用,降低了 GC 导致的服务暂停和 OOM 风险

  • 减少了大批量频繁内存拷贝的时间,能大幅优化数据吞吐性能

所以很有必要进行这样的优化

Kafka 的实例是运行在 JVM 里的,零拷贝的技术落地也离不开 Java 运行时提供的环境,具体到实现上主要依赖 Java 提供的 FileChannel 去映射文件

针对消息拉取消费的场景,直接将日志段 FileChannel 中对应偏移和长度(Kafka 的日志段都有对应的索引文件,所以不需要读取原始消息日志段文件就能拿到这些信息)的数据发送到网络栈,规避应用层的数据拷贝中转

针对消息推送生产的场景,从网络栈读取出来处理好的消息直接从内存 Buffer 中向 FileChannel 写入追加,当然这个场景并没有实现严格意义上的零拷贝(JVM 堆内存存在于用户空间,写入文件中必须要拷贝到内核),只不过 Kafka 用了 MemoryRecords 这个类基于 Buffer 去管理内存中的消息,规避了使用对象结构的方式管理可能存在的内存拷贝和数据序列化行为(这个优化的思路和 String 以及 StringBuilder 一致)

这里只是以场景的例子提供一些分析零拷贝实现机制的视角(系统原生支持 + 处理逻辑层面优化),零拷贝单独展开也是一个很大的话题,总体来讲就是在各个环节尽可能减少内存拷贝的次数,提高数据读写性能

角色和实体

在 Kafka 对上述消息模型的实现中,定义了一系列负责执行的角色和表达数据结构的实体,每个角色和实体都有其对应的责任边界,这些角色和实体之间共同配合完成整个消息引擎的运作

Kafka 中有这么一些比较重要的角色和实体:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: RabbitMQ和Kafka都是消息队列系统,但它们的使用场景略有不同。 RabbitMQ适用于需要可靠消息传递的场景,例如金融交易、电子商务等。它支持多种消息传递模式,包括点对点、发布/订阅、工作队列等。RabbitMQ还提供了高级功能,如消息确认、持久化、优先级等,可以确保消息传递的可靠性和稳定性。 Kafka适用于需要高吞吐量的场景,例如日志收集、流处理等。它采用分布式架构,可以轻松地扩展到多个节点,支持高并发的消息传递。Kafka还提供了流处理功能,可以实时处理数据流,支持复杂的数据转换和分析。 总之,选择RabbitMQ还是Kafka,取决于具体的业务需求和场景。 ### 回答2: RabbitMQ和Kafka都是流行的消息代理系统,它们的使用场景有所不同。 RabbitMQ适合处理复杂、逻辑较强的消息传递场景,比如高可靠性、高并发、多样的消息传递方式。RabbitMQ支持多种消息传递模式,包括点对点、发布/订阅、消息队列和主题等,可以满足不同场景下的需求。RabbitMQ的广泛使用场景包括电子商务、金融交易、电信网络等。RabbitMQ的高可靠性、高吞吐量、大规模集群和灵活的体系结构,使得它能够应对各种复杂的消息传递需求。 而Kafka则专注于高吞吐量、高度可扩展的消息传递场景,以简单、高效、快速为目标。Kafka具有高度的可扩展性,容易与其他系统集成,适合处理流数据(例如日志、实时监控数据、事件数据等)。Kafka使用发布/订阅模式实现消息传递,其优势在于可以快速地处理大规模数据,而不必担心吞吐量或性能问题。由于Kafka的高效性和可扩展性,它被广泛用于分布式系统、大数据处理、日志收集和实时分析等领域。 综上所述,RabbitMQ和Kafka分别适用于不同的场景和需求。对于有复杂逻辑、多样的消息传递方式和高可靠性要求的应用场景,RabbitMQ是一个不错的选择。如果是需要快速、高效地处理大量数据,且需要高度的可扩展性和可靠性,那么Kafka则更加适合。当然,在实际应用中也有可能需要同时使用两个消息代理系统来实现不同的消息传递需求。 ### 回答3: RabbitMQ 和 Kafka 都是消息队列系统,不同之处在于其设计的重点不同,因此在使用场景上也有所不同。 RabbitMQ 适用于需要高度可靠性和灵活性的应用场景。它为开发人员提供了一些很好的特性,如事务、优先级队列、消息确认和持久化等。这些特性使得 RabbitMQ 能够确保消息不会丢失并且确保消息会按照正确的顺序被处理。RabbitMQ 通常用于企业级应用程序中,如金融、电信、电子商务等领域,因为这些行业对于数据的安全和可靠性要求较高。 Kafka 适用于需要处理大量数据的应用场景,例如日志处理、大数据分析等。 Kafka 的设计使其可以处理数TB的数据,能够扩展以处理需要处理的数据的增长,同时保证很高的吞吐量和低延迟。凭借其分布式、可伸缩性的架构Kafka 被广泛应用于社交媒体、移动应用程序、在线广告等领域。 综上所述,RabbitMQ 和 Kafka 在不同的场景下各有其优势。RabbitMQ 适用于高可靠性、有高要求子业务时的应用,而 Kafka 更适合处理大数据流,能够扩展以处理需要处理的数据的增长,同时保证高吞吐量和低延迟。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值