https://www.itzhai.com/articles/deep-understanding-of-kafka.html
基本概念
Kafka基本概念:
Broker
:Kafka
以Broker
集群的方式运行,一个Kafka节点就是一个Broker。理论上可以跨越多个数据中心。Broker负责数据复制,管理主题、分区、消费偏移量等。如果要跨越多个数据中心,数据中心之间的网络延迟需要非常低,因为Kafka Broker之间以及Broker和Zookeeper服务器之间有大量的通信。
在上图中,Kafka集群中包含3个Broker
。
Topic
:即主题,与RocketMQ
的Topic
类似,使用Topic
对消息进行分类,Kafka
接收到的每条消息都会放入到一个Topi
c中。
Topic
代表发布和消费记录的端点。生产者向主题发布消息,消费者订阅主题进行消费消息;
每条记录有一个键,一个值,一个时间戳和一些元数据组成; 在未指定分区的情况下发布消息时,将使用键的散列选择分区。
Producer
:消息生产者,负责向Broker
发送消息;
Consumer
:消息消费者,从负责Broker
读取并消费消息;
ConsumerGroup
:消费分组,对于同一个主题,可以被多个消费分组分别消费,每个消费分组有自己的消费偏移量,互不影响;
Partition
:分区,对Topic
的数据进行分布式存储的最小单位。
存储架构
Kafka是以分区为维度进行存储的 每个Partition分区下面是由多个Segment(段)组成的,Segment是逻辑概念,实际上会对应到上面的三个文件 log:数据文件,存储实际的消息数据; index:索引文件,存储消息数据的索引; timeindex:索引文件,提供时间维度的检索。
Segment文件的命名规则:Partition的第一个Segment文件从0开始,后续每生成一个新的Segment文件的时候,文件名以当前Partition的最大offset为基准,文件名长度为64位long类型。 Segment生成相关配置:
log.segment.bytes: 每个segment的大小,达到这个大小后会创建一个新的segment,默认是1G; log.segment.ms: 配置每隔多少毫秒产生一个新的segment,默认是7天。
kafka 集群特性
每个Topic可以配置为多个分区,每个分区可以有多个副本,副本称为Replica,在副本集合中会存在一个Leader副本, Leader负责所有的读写请求,其余副本只负责从Leader同步备份数据。
Isr(In-Sync Replica):是Replicas的一个子集,列出当前还存活着,并且已经同步备份了该分区的节点。
Isr中包括Leader副本,以及与Leader副本保持同步的Follower副本。
Rebalance机制
Rebalance机制是Kafka消费机制的核心。
当消费组消费者数量发生变化、或者消费组消费主题数量变化、主题分区数量变化等的时候,Kafka会重新分配消费者和分区的关系,也就是做一次Rebalance。
**Kafka保证一个Topic分区只会配给一个组内的消费者,**而一个消费者可以消费多个分区。
Rebalance策略主要有三种:Range、RoundRobin、StickyAssignor(粘性分配器)
Range:分区数除于消费者总数 RangeAssignor有何缺点? 消费组中的消费者数量多于主题的分区数量,并没有尽可能地使用到所有的消费者
轮循: RoundRobin有何缺点? 虽然RoundRobin尽可能的利用所有的消费者,但是一旦消费者数量发生变化触发Rebalance时,会导致更多的分区重分配。
StickyAssignor:分区尽可能保证分布均匀,分区分配尽可能保持不变更
Kafka是如何保证数据的可靠性?
生产者:acks=all,并且使用同步阻塞的方式发送消息; Topic:replication.factor >= 3,min.insync.replicas >= 2; Broker:unclean.leader.election.enable=false,确保ISR集合中没有可用的在线副本时,不会去选举ISR之外的副本作为新的Leader。
消费端:为了避免丢失未处理完的消息,需要设置为手动提交
Kafka为啥性能这么高?
大家知道RocketMQ是基于Kafka改造而来的,因此Kafka的高性能原因与RocketMQ类似,以下是Kafka高性能的原因:
磁盘顺序读写:Kafka写消息都是直接追加到文件末尾的,不会有随机写的情况,另外,不会随机删除日志,只会按照删除策略删除一整段的历史消息。 与RocketMQ不同的是,kafka不会像RocketMQ那样预分配一个很大的文件来存储消息,Kafka的顺序写可以理解为分段顺序写的,一般一台服务器只部署Kafka就更接近与完全顺序; 批量读写数据,以及压缩传输: Rocket发送消息底层是分批发送的,提高了传输和存储的效率; 数据零拷贝技术:通过mmap内存映射,以及sendfile,减少了数据拷贝次数,提高了数据发送效率。
消息顺序性如何保证
发送端设置同步发送,避免异步发送导致乱序; 消费端消息统一发到同一个分区,通过一个消费者去消费消息。