Kafka 之初次相识
参考
定义
Kafka 是最初由 Linkedin 公司开发,是一个分布式、支持分区的(Partition)、多副本的(Replication),基于 Zookeeper
协调的分布式消息系统。
Kafka 的特性
高吞吐量、低延迟
:每秒可以处理几十万条消息,它的延迟最低只有几毫秒。可扩展性
:集群支持热扩展。持久性
、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失。容错性
:允许集群中节点失败(若副本数量为 n,则允许 n-1 个节点失败)。高并发
:支持数千个客户端同时读写。
Kafka 优点
- 性能卓越:单机写入
TPS 约在 百万条/秒
,最大的优点,就是吞吐量高。 - 时效性:毫秒级(ms)。
- 可用性:非常高,Kafka 是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用。
- 消息有序:消费者采用
pull
方式获取消息,消息有序,通过控制能够保证所有消息被消费且仅被消费一次。 - 管理界面:有优秀的第三方 Kafka 有 Web 管理界面
Kafka-Manager
- 日志领域:在日志领域比较成熟,被多家公司和多个开源项目使用。
- 功能支持:功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用。
Kafka 缺点
- Kafka 单机超过
64
个队列/分区,Load
会发生明显的飙高现象,队列越多,Load
越高,发送消息响应时间变长。 - 使用短轮询方式,实时性取决于轮询间隔时间。
- 消费失败不支持重试。
- 支持消息顺序,但是一台代理宕机后,就会产生消息乱序。
- 社区更新较慢。
基础架构与名词解释
Producer
Producer 即 生产者
,消息的产生者,是消息的入口。
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 即 消费者
,消息的消费方,是消息的出口。
Consumer Group
我们可以将多个消费组组成一个 消费者组
,在 Kafka 的设计中同一个分区的数据只能被消费者组中的某一个消费者消费。
同一个消费者组的消费者可以消费同一个 Topic 的不同分区的数据,这也是为了提高 Kafka 的吞吐量。
Zookeeper
Kafka 集群依赖 Zookeeper
来保存集群的的元信息,来保证系统的可用性。
工作流程分析
第一步:发送数据
producer
先从集群获取分区的leader
。producer
将消息发送给leader
。leader
将消息写入本地文件。followers
从leader
中pull
消息。followers
将消息写入本地后,向leader
发送ACK
。leader
收到所有followers
的ACK
后,向producer
发送ACK
。
分区的主要目的:
- 方便扩展:因为一个 Topic 可以有多个 Partition,所以我们可以通过扩展机器去轻松的应对日益增长的数据量。
- 提高并发:以 Partition 为读写单位,可以多个消费者同时消费数据,提高了消息的处理效率。
Kafka 中分区(Partition)有几个原则:
- Partition 在写入的时候可以指定需要写入的 Partition。
- 如果有指定,则写入对应的 Partition。
- 如果没有指定,但是设置了数据的 key,则会根据 key 的值 hash 出一个 Partition。
- 如果既没指定,又没有设置 key,则会轮询选出一个 Partition。
ACK 参数:
0
代表 producer 往集群发送数据不需要等到集群的返回,不确保消息发送成功。安全性最低但是效率最高。1
代表 producer 往集群发送数据只要 leader 应答就可以发送下一条,只确保 leader 发送成功。-1
(all)代表 producer 往集群发送数据需要所有的 follower 都完成从 leader 的同步才会发送下一条,确保 leader 发送成功和所有的副本都完成备份。安全性最高,但是效率最低。
第二步:保存数据
Kafka 初始会单独开辟一块磁盘空间,顺序写入数据(效率比随机写入高)。
Partition 结构:
- 每个
Partition
的文件夹下面会有多组segment
文件。 - 每组
segment
文件又包含.index
文件.log
文件.timeindex
文件(早期版本中没有)三个文件。 log
文件就实际是存储message
的地方,而index
和timeindex
文件为索引文件,用于检索消息。
Message 结构:
- offset:
offset
是一个占8 byte
的有序 id 号,它可以唯一确定每条消息在 Partition 内的位置。 - 消息大小:消息大小占用
4 byte
,用于描述消息的大小。 - 消息体:消息体存放的是实际的消息数据(被压缩过),占用的空间根据具体的消息而不一样。
存储策略:
无论消息是否被消费,Kafka 都会保存所有的消息。那对于旧数据有什么删除策略呢?
- 基于时间,默认配置是
168 小时
(7 天
)。 - 基于大小,默认配置是
1073741824
。
Kafka 读取特定消息的时间复杂度是 O(1)
,所以这里删除过期的文件并不会提高 Kafka 的性能。
第三步:消费数据
- Kafka 采用的是发布订阅模式,消费者主动的去 Kafka 集群拉取消息,与 Producer 相同的是,消费者在拉取消息的时候也是找 Leader 去拉取。
- 多个消费者可以组成一个消费者组,每个消费者组都有一个组 id,同一个消费组者的消费者可以消费同一 Topic 下不同分区的数据,但是不会组内多个消费者消费同一分区的数据。
- 建议消费者组的 Consumer 的数量与 Partition 的数量一致
Kafka 是否可以保证消息的顺序性?
Kafka 不能保证整个 Topic 中的消息是有序的,只能保证每个 Partition
中的消息是有序的。