https://www.itzhai.com/articles/deep-understanding-of-kafka.html

基本概念

Kafka基本概念:

BrokerKafkaBroker集群的方式运行,一个Kafka节点就是一个Broker。理论上可以跨越多个数据中心。Broker负责数据复制,管理主题、分区、消费偏移量等。如果要跨越多个数据中心,数据中心之间的网络延迟需要非常低,因为Kafka Broker之间以及Broker和Zookeeper服务器之间有大量的通信。 在上图中,Kafka集群中包含3个BrokerTopic:即主题,与RocketMQTopic类似,使用Topic对消息进行分类,Kafka接收到的每条消息都会放入到一个Topic中。 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,减少了数据拷贝次数,提高了数据发送效率。

消息顺序性如何保证

发送端设置同步发送,避免异步发送导致乱序; 消费端消息统一发到同一个分区,通过一个消费者去消费消息。