kafka-基础--基本原理1
1. kafka基础架构
生产者(producer)
消息的产生者,是消息的入口。
kafka集群(Kafka Cluster):
Broker:Broker 是 Kafka 实例,每个服务器上有一个或多个 Kafka 的实例,我们姑且认为每个 Broker 对应一台服务器。
每个 Kafka 集群内的 Broker 都有一个不重复的编号,如图中的 Broker-0、Broker-1 等……
Topic:消息的主题,可以理解为消息的分类,Kafka 的数据就保存在 Topic。在每个 Broker 上都可以创建多个 Topic。
Partition:Topic 的分区,每个 Topic 可以有多个分区,分区的作用是做负载,提高 Kafka 的吞吐量。
同一个 Topic 在不同的分区的数据是不重复的,Partition 的表现形式就是一个一个的文件夹!
Replication:每一个分区都有多个副本,副本的作用是做备胎。当主分区(Leader)故障的时候会选择一个备胎(Follower)上位,成为 Leader。
在 Kafka 中默认副本的最大数量是 10 个,且副本的数量不能大于 Broker 的数量,Follower 和 Leader 绝对是在不同的机器,
同一机器对同一个分区也只可能存放一个副本(包括自己)。
Message:每一条发送的消息主体。
Consumer:消费者,即消息的消费方,是消息的出口。
Consumer Group:我们可以将多个消费者组成一个消费者组,在 Kafka 的设计中同一个分区的数据只能被消费者组中的某一个消费者消费。
同一个消费者组的消费者可以消费同一个 Topic 的不同分区的数据,这也是为了提高 Kafka 的吞吐量!
Zookeeper:Kafka 集群依赖 Zookeeper 来保存集群的的元信息,来保证系统的可用性。
2. 写入数据
写入数据流程
1、先从集群获取分区的leader
2、producer将消息发送给leader
3、leader将消息写入到本地文件
4、flowers从leader拉取消息
5、flowers将消息写入到本地后向leader发送ACK
6、leader收到所有的ACK后向producer发送ACK
分区
Producer 采用 Push 模式将数据发布到 Broker,每条消息追加到分区中,顺序写入磁盘
分区的主要目的是:
方便扩展。因为一个 Topic 可以有多个 Partition,所以我们可以通过扩展机器去轻松的应对日益增长的数据量。
提高并发。以 Partition 为读写单位,可以多个消费者同时消费数据,提高了消息的处理效率。
producer向分区写入数据的原则:
Partition 在写入的时候可以指定需要写入的 Partition,如果有指定,则写入对应的 Partition。
如果没有指定 Partition,但是设置了数据的 Key,则会根据 Key 的值 Hash 出一个 Partition。
如果既没指定 Partition,又没有设置 Key,则会轮询选出一个 Partition。
partition结构
每个 Topic 都可以分为一个或多个 Partition
Partition 在服务器上的表现形式就是一个一个的文件夹,每个 Partition 的文件夹下面会有多组 Segment 文件。
每组 Segment 文件又包含 .index 文件、.log 文件、.timeindex 文件(早期版本中没有)三个文件。
Log 文件就是实际存储 Message 的地方,而 Index 和 Timeindex 文件为索引文件,用于检索消息。
文件的命名是以该 Segment 最小 Offset 来命名的,如 000.index 存储 Offset 为 0~368795 的消息,
Kafka 就是利用分段+索引的方式来解决查找效率的问题。
Message结构
存储在 Log 中的 Message 包含消息体、消息大小、Offset、压缩类型……等等
Offset:Offset 是一个占 8byte 的有序 id 号,它可以唯一确定每条消息在 Parition 内的位置!
消息大小:消息大小占用 4byte,用于描述消息的大小。
消息体:消息体存放的是实际的消息数据(被压缩过),占用的空间根据具体的消息而不一样。
确保写入数据不丢失方法(ACK 应答机制)
在生产者向队列写入数据的时候可以设置参数来确定是否确认 Kafka 接收到数据,这个参数可设置的值为 0、1、all:
0 代表 Producer 往集群发送数据不需要等到集群的返回,不确保消息发送成功。安全性最低但是效率最高。
1 代表 Producer 往集群发送数据只要 Leader 应答就可以发送下一条,只确保 Leader 发送成功。
all 代表 Producer 往集群发送数据需要所有的 Follower 都完成从 Leader 的同步才会发送下一条,
确保 Leader 发送成功和所有的副本都完成备份。安全性最高,但是效率最低。
保存数据
Producer 将数据写入 Kafka 后,集群就需要对数据进行保存了!Kafka 将数据保存在磁盘,
可能在我们的一般的认知里,写入磁盘是比较耗时的操作,不适合这种高并发的组件。
Kafka 初始会单独开辟一块磁盘空间,顺序写入数据(效率比随机写入高)
无论消息是否被消费,Kafka 都会保存所有的消息。
对于旧数据的删除策略
基于时间,默认配置是 168 小时(7 天)。
基于大小,默认配置是 1073741824
3. 消费数据
消费者与分区
一般消息队列采用了点对点和发布订阅的模式
Kafka 采用的是点对点的模式,消费者主动的去 Kafka 集群拉取消息,
与 Producer 相同的是,消费者在拉取消息的时候也是找 Leader 去拉取
多个消费者可以组成一个消费者组(Consumer Group),每个消费者组都有一个组 id
同一个消费者组的消费者可以消费同一 Topic 下不同分区的数据,但是不会组内多个消费者消费同一分区的数据
在实际的应用中,建议消费者组的 Consumer 的数量与 Partition 的数量一致
查找消息
利用 Segment+Offset 配合查找
例如查找一个 Offset 为 368801 的 Message
先找到 Offset 的 368801message 所在的 Segment 文件(利用二分法查找),这里找到的就是在第二个 Segment 文件。
打开找到的 Segment 中的 .index 文件(也就是 368796.index 文件,该文件起始偏移量为 368796+1。
要查找的 Offset 为 368801 的 Message 在该 Index 内的偏移量为 368796+5=368801,所以这里要查找的相对 Offset 为 5
由于该文件采用的是稀疏索引的方式存储着相对 Offset 及对应 Message 物理偏移量的关系,所以直接找相对 Offset 为 5 的索引找不到。
这里同样利用二分法查找相对 Offset 小于或者等于指定的相对 Offset 的索引条目中最大的那个相对 Offset,所以找到的是相对 Offset 为 4 的这个索引。
根据找到的相对 Offset 为 4 的索引确定 Message 存储的物理偏移位置为 256。
打开数据文件,从位置为 256 的那个地方开始顺序扫描直到找到 Offset 为 368801 的那条 Message。
在早期的版本中,消费者将消费到的 Offset 维护在 Zookeeper 中,Consumer 每间隔一段时间上报一次,
这里容易导致重复消费,且性能不好!
在新的版本中消费者消费到的 Offset 已经直接维护在 Kafka 集群的 __consumer_offsets 这个 Topic 中!
4. Kafka速度为什么这么快
Kafka的消息是保存或缓存在磁盘上的,一般认为在磁盘上读写数据是会降低性能的,
因为寻址会比较消耗时间,但是实际上,Kafka的特性之一就是高吞吐率。
即使是普通的服务器,Kafka也可以轻松支持每秒百万级的写入请求,
超过了大部分的消息中间件,这种特性也使得Kafka在日志处理等海量数据场景广泛应用。
Kafka会把收到的消息都写入到硬盘中,它绝对不会丢失数据。为了优化写入速度Kafka采用了两个技术, 顺序写入和MMFile 。
Kafka速度的秘诀在于,它把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络IO损耗,
通过mmap提高I/O速度,写入数据的时候由于单个Partion是末尾添加所以速度最优;读取数据的时候配合sendfile直接暴力输出。
5. 参考
仅需3分钟,你就能明白Kafka的工作原理 https://mp.weixin.qq.com/s/Rv59axzzF0aokHfG03HudA