透彻理解Kafka(一)——整体架构

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

从本系列开始,我将对Kafka这一流行的分布式消息中间件进行透彻分析。我之前在MQ系列中,对RocketMQ的核心原理进行过讲解,其实它俩在设计上有很多相似地方。

Kafka 是 Linkedin 采用 Scala 语言开发的 一个 多分区 、 多副本 、 基于 ZooKeeper 的分布式消息系统,现己被捐献给 Apache 基金会 。 目前 Kafka 已经定位为一个分布式流式处理平台,它以高吞吐低延迟、可持久化、可水平扩展、支持流数据处理等多种特性而被广泛使用。

本章,我会从整体上对Kafka的基本架构和一些核心概念做阐述,便于读者初步了解Kafka,后续章节再对细节作详述。

一、核心组件

在Kafka中,一共有四个核心组件: Zookeeper集群 、 Broker 、 Producer 、 Customer ,它们之间的基本关系可以用下面这张图表示:

Zookeeper集群: 负责Kafka集群的元数据管理、控制器选举等操作;
Producer: 生产者,也就是发送消息的一方,负责创建消息,然后将其投递到Kafka中;
Consumer :消费者,也就是接收消息的一方,消费者连接到 Kafka 上并接收消息,进行相应的业务逻辑处理;
Broker :Broker 可以简单地看作一个独立的 Kafka服务节点或Kafka 服务进程实例,一个或多个 Broker 组成了 一个 Kafka 集群。一般而言,生产环境一台服务器运行一个Broker进程。

## 二、高性能

Kakfa之所以具有高吞吐低延迟的特性,核心有四个点:

- 顺序读写磁盘;
- MMap内存映射技术;
- 零拷贝技术;
- 数据批处理。

2.1 顺序读写磁盘

Kafka在持久化消息的时候,仅仅是将消息追加到日志文件的末尾,也就是 磁盘顺序写 ,性能极高。

2.2 MMap内存映射

MMAP 也就是 内存映射文件 ,在64位操作系统中一般可以表示 20G 的数据文件,它的工作原理是直接利用操作系统的 Page 来实现文件到物理内存的直接映射,完成映射之后对物理内存的操作会被同步到硬盘上。

通过 MMAP 技术,进程可以像读写硬盘一样读写内存(逻辑内存),不必关心内存的大小,因为有虚拟内存兜底。这种方式可以极大的提升I/O能力,省去了数据从用户空间到内核空间复制的开销。

但是这里要注意:写到 MMAP 中的数据并没有真正写到硬盘,操作系统会定时进行刷盘操作,将Page Cache中的数据flush到磁盘。

Kafka提供了producer.type参数,来控制是否同步刷盘。

2.3 零拷贝

Consumer在消费消息时,会请求Kafka Broker从磁盘文件里读取消息,然后通过网络发送出去,整个流程涉及到了 零拷贝 ,如下图:

可以看到,Kafka Broker利用了Linux的sendfile函数,直接把读取操作交给OS,OS会查看Page Cache中是否有数据,如果没有就从磁盘上读取并缓存到Page Cache,如果有就直接将OS Cache里的数据拷贝给网卡引擎,这样就减少了上下文切换和数据复制的开销。

2.4 数据批处理

当Consumer需要消费数据时,首先想到的是消费一条,Kafka发送一条。但实际上,Kafka 会把一批消息压缩存储,当消费者拉取数据时,实际上是拉到一批数据。比如说100万条消息压缩放到一个文件中可能就是10M的数据量,如果消费者和Kafka之间网络良好,10MB大概1秒就能发送完,即Kafka每秒处理了100万条消息。

正是因为这种批处理的方式,Kafka才有了极高的吞吐量。

三、可扩展

3.1 数据分片

Kafka 中的消息以 主题(Topic) 为单位进行归类,生产者发送消息时,必须指定消息的主题,而消费者负责订阅主题并进行消费。

主题(Topic)是一个 逻辑 上的概念,它可以细分为多个分区,同一主题下的不同分区包含的消息是不同的,各个分区构成了一个完整的数据集,这实际上就是 数据分散集群 的模式。

分区(Partition) 在存储层面可以看作一个可追加的日志( Log )文件,消息在被追加到分区日志的时候都会分配一个特定的偏移量( offset )。 offset 是消息在分区中的唯一标识, Kafka 通过它来保证消息在分区内的顺序性,不过 offset 并不跨越分区,也就是说, Kafka 保证的是分区有序而不是主题有序 。

四、高可用

4.1 多副本冗余

Kafka为了维持集群的高可用,引入了 副本(Replica) 机制,每个分区都可以有多个副本,同一分区的不同副本中保存的消息是相同的。 Kafka会选举出一个Leader副本,负责处理 读写 请求 ,其它Follower副本只负责与Leader进行消息同步。

Kafka可以通过多副本机制实现故障的自动转移,当 Kafka 集群中某个 broker 挂掉时,各个副本重新选举leader,最终保证服务可用。

我通过下面一张图来总结下主题(Topic)、分区(Partition)、副本(Replica)这三个概念。下图中,两个Broker进程组成了一个Kafka集群,然后创建了一个主题,这个主题有3个分区,每个分区有2个副本。Kafka会自动均匀分布同一个分区的不同副本到不同的Broker上:

4.2 故障自动转移

Kafka基于Zookeeper实现了故障节点的发现与自动转移。当一个分区的Leader副本挂掉后,其它Follower副本会选举出新的Leader,并往Zookeeper中注册信息。

五、数据同步

5.1 ISR/OSR

每个分区的follower副本都会从leader同步消息数据,既然是同步,就一定有滞后性。这里引申出Kafka中的三个概念:

  • AR ( Assigned Replicas ): 在Kafka中,分区中的所有副本(包含Leader)统称为 AR;
  • ISR (On-Sync Replicas ): 所有与 Leader 保持一定程度同步的副本(包括 leader在内)组成 ISR;
  • OSR ( Out-of-Sync Replicas): 与Leader 副本同步滞后过多的副本(不包括 leader 副本)组成 OSR 。

通过上面的描述可以看出: AR = ISR + OSR 。

Leader 负责维护和跟踪 ISR 集合中所有 follower副本的滞后状态(Leader会维护每个Follower的LEO,Follower来拉取消息时会带上自己的LEO),当follower副本落后太多或失效时,leader 会把它从 ISR 集合中剔除,转移到OSR。默认情况下, 当 leader 副本发生故障时,只有在 ISR 集合中的副本才有资格被选举为新的 leader。

5.2 HW和LEO

那么,到底怎么样才算同步滞后过多呢?这就又涉及到 HW(High Watermark,高水位) 和 *LEO(Log End Offset)*两个概念了。

  • HW(High Watermark,高水位) : 标识了 一个特定的消息偏移量( offset ),消费者只能拉取到这个 offset 之前的消息;
  • LEO(Log End Offset) :标识了当前日志文件中的下一条待写入消息的offset。

我通过下面这张图来讲解上述的概念:

上图是某个分区的某个副本中的日志文件,这个日志文件中一共有9条消息,第一条消息的offset=0,最后一条消息的offset=8,offset 为 9 的位置用虚线框表示,代表下一条待写入的消息。

上述日志文件的HW=6,表示Consumer只能拉取到 offset 在 0 至 5 之间的消息,offset为6~8之间的消息对Consumer是不可见的;offset = 9 的位置即为当前日志文件的 LEO,所以LEO的大小相于当前日志中的最后一条消息的offset +1。

ISR 集合中的每个副本都会维护自身的 LEO ,而 ISR 集合中最小的 LEO即为这个分区的HW ,对于消费者而言,只能消费HW之前的消息。

Kafka之所以引入ISR机制,是为了有效地权衡 数据可靠性 和 性能 之间的关系,因为完全同步复制影响性能,完全异步复制又可能因为follower落后太多宕机后导致消息丢失。我后面章节会再对ISR机制进行更详细的分析。

六、总结

本章,我先从整体上对Kafka的核心功能和架构进行了分析,从后续章节开始,我将对Kafka每一个组件进行深入剖析。

  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值