20-Kafka
Kafka
是一个一个分布式流处理平台,高吞吐量、分布式、持久性、可伸缩性
Kafka不支持在Broker层面进行消息过滤
Kafka 3.3之后已经可以不依赖zookeeper了
特性
- 可以让你发布和订阅流式的记录。这一方面与消息队列或者企业消息系统类似
- 可以储存流式的记录,并且有较好的容错性。
- 可以在流式记录产生时就进行处理。
应用场景
- 构造实时流数据管道,它可以在系统或应用之间可靠地获取数据。 (相当于message queue)
- 构建实时流式应用程序,对这些流数据进行转换或者影响。 (就是流处理,通过kafka stream topic和topic之间内部进行变化)
基础架构
Producer(生产者):生产者是发送消息到Broker集群。生产者将消息发送到指定的主题,Kafka根据配置的分区策略(如轮询、按键哈希等)将消息分配到不同的分区。
Consumer(消费者):消费者从Broker读取消息。消费者可以独立运行或分组在一起运行。分组中的消费者共享订阅的主题,Kafka平衡各个消费者的负载,确保每个分区只被组内的一个消费者读取
Broker(消息代理服务器):Broker是Kafka集群中的一个服务器,负责存储数据和处理对数据的读写请求。每个Broker可以存储一个或多个主题的数据。一个Kafka集群可以包含多个Broker,以提高容量和提供容错能力。
Topic(主题): Topic是逻辑概念。生产者写入消息到指定的Topic,消费者从Topic读取消息。Topic在逻辑上被分割为一个或多个分区,这允许数据在多个Broker之间进行负载均衡。
Partition(分区): 分区是Topic的物理分段,每个分区是一个有序的、不可变的消息日志。分区可以分布在集群中的不同Broker上。每个分区都由一系列有序的、不断增加的消息组成,每条消息都被分配一个顺序的标识符称为偏移量。
ZooKeeper:Kafka使用ZooKeeper来维护集群状态、配置信息和进行领导者选举。
日志存储机制
- 日志文件: Kafka 所有的消息以日志的形式存储在磁盘上,并且每个Partition都是一个连续的日志文件。
- 追加写入: Kafka采用追加写入的方式存储消息到日志文件中,新消息被添加到文件的末尾,这种方式对于磁盘I/O是非常高效的,因为它大部分是顺序写入,从而极大地提高了写入速度。但是当Partition数量过多时,顺序写就变成了随机写,性能下降。
- 索引文件: 为了快速查找和读取特定消息,Kafka为每个日志文件维护一个索引文件。索引文件存储消息在日志文件中的偏移量和其对应在文件中的物理位置,这样可以在不读取整个日志文件的情况下直接跳转到特定的消息。
存储机制
- Kafka的Topic被分为多个分区,分区是是按照Segments存储文件块。
- LEO: log end offset 标识的是每个分区中最后一条消息的下一个位置,分区的每个副本都有自己的 LEO.
- HW: high watermarker称为高水位线,所有HW之前的的数据都理解是已经备份的,当所有节点都备 份成功,Leader会更新水位线。
- ISR:In-sync-replicas,kafka的leader会维护一份处于同步的副本集合,如果在
replica.lag.time.max.ms
时间内系统没有发送fetch请求,或者已然在发送请求,但是在该限定时间内没有赶上Leader的数据就被剔除ISR列表。在Kafka-0.9.0版本剔除
leader epoch
- 任意一个Leader持有一个LeaderEpoch。该LeaderEpoch这是一个由Controller管理的32位数字,存储在Zookeeper的分区状态信息中,并作为LeaderAndIsrRequest的一部分传递给每个新的Leader。Leader接受Producer请求数据上使用LeaderEpoch标记每个Message。然后,该LeaderEpoch编号将通过复制协议传播,并用于替换HW标记,作为消息截断的参考点
高可用机制
- 副本机制: Kafka通过副本(replicas)机制确保数据的安全性。每个Topic可以被配置为一个或多个分区(partitions),每个分区可以有一个或多个副本。副本分布在不同的Broker上,这样即使一个或多个Broker发生故障,Topic的数据也不会丢失。
- 领导者和追随者: 每个分区有一个领导者(leader)和多个追随者(followers)。所有的读写请求都由领导者处理,而追随者则从领导者那里复制数据。如果领导者发生故障,系统会从追随者中选举出新的领导者。
- 控制器(Controller): 控制器是一个特殊的Broker节点,负责维护领导者的选举和副本状态的管理。如果控制器出现故障,集群中的其他Broker将通过选举产生新的控制器。
- ZooKeeper协调: Kafka使用ZooKeeper来管理集群元数据和进行Broker之间的协调,包括领导者选举和集群成员管理。
- 高水位标记(high watermark): Kafka为每个分区维护一个“高水位”(high watermark)标记,这是所有同步副本已确认写入的最小偏移量。只有高于高水位的消息才被认为是“提交”的,消费者只能读取到这些已提交的消息。这保证了即使在发生故障的情况下,消费者也不会读取到可能因故障而回滚的消息。
消息可靠性
复制
- Kafka通过在多个Broker中复制每个Topic的Partition来增加数据的可靠性和系统的容错性。这意味着每个Partition都有一个Leader和多个Follower。所有的写操作都通过Leader进行,而Follower从Leader同步数据。如果Leader失败,一个Follower将被自动选举为新的Leader,确保服务的连续性和数据的可用性。
确认机制
- 生产者在发送消息时可以指定不同级别的确认机制来保证消息的可靠传递:
- acks=0:生产者在写入消息后不会等待任何服务器的确认,这种模式下消息可能会丢失,但延迟最低。
- acks=1:生产者会等待Leader确认消息已被写入本地日志后才考虑完成请求。这种模式下,如果在Follower复制之前Leader发生故障,消息可能会丢失。
- acks=all 或 acks=-1:生产者会等待所有同步副本都确认消息已被接收,才认为消息发送成功。这提供了最高的数据可靠性保证。
事务支持
- 从0.11版本开始,Kafka引入了事务API,支持跨多个Partition的原子写操作。这意味着生产者可以发送一批消息,这些消息要么全部成功写入,要么全部失败,从而防止了在处理复杂业务逻辑时出现部分更新的情况。
持久化
- Kafka默认将所有消息持久化到磁盘,这不仅确保了数据在系统重启后的可恢复性,还能保护数据不受系统故障的影响。Kafka通过顺序写磁盘的方式优化了I/O性能,即使是在高负载下也能保持高吞吐量。
高水位
- Kafka为每个Partition维护一个高水位标记,这表示所有同步副本都确认接收到的最小偏移量。消费者只能读取到高水位之前的消息,这保证了消费者只看到已经被所有同步副本确认的消息,增加了读操作的一致性。
顺序消息
- Kafka支持单分区有序
消息重试
- Kafka支持生产者发送消息失败的时候自动重试,不支持消费者消费消息失败时重试。
消息回溯
- 基于偏移量回溯:
- 消费者可以直接指定队列的偏移量来回溯消息。这种方式需要消费者知道具体的偏移量。
- 基于时间戳回溯:
- 消费者根据时间戳来重置消费进度。这种方式适用于希望从某一特定时间点重新开始消费消息的场景。
参考文章
20-Kafka
https://x-leonidas.github.io/2022/02/01/11技术栈/MQ/20-Kafka/