
kafka体系结构

Producer 生产者
Consumer 消费者
Broker 服务代理节点(集群节点)
还有一个重要的概念
Topic 主题
Partition 分区
一个分区只属于一个Topic,一个主题可以有多个分区分布在不同的broker上
每个分区可以有多个副本
Leader replica
follower replica
生产者和消费者只和Leader副本打交道,读写都在Leader副本上
follower副本只负责消息同步,follower副本中的消息相对于leader副本会有一定的滞后
副本的划分
AR ISR OSR
分区中的所有副本统称为AR(Assigned Replicas)
与leader副本保持消息同步的副本组成ISR (in-sync rplicas)
与leader副本消息同步滞后过多的副本组成OSR
leader副本负责维护和跟踪ISR集合中所有follower副本的滞后状态,当follower副本落后太多或失效时,leader副本会把它从ISR集合中剔除。如果OSR集合中有follower副本“追上”了leader副本,那么leader副本会把它从OSR集合转移至ISR集合。默认情况下,当leader副本发生故障时,只有在ISR集合中的副本才有资格被选举为新的leader,而在OSR集合中的副本则没有任何机会(不过这个原则也可以通过修改相应的参数配置来改变)
offset划分
HW (High Watermark) 标识一个特定消息的偏移量,消费者只能拉取到HW offset之前的消息;
LEO (Log End Offset) 副本日志文件待写入的消息
HW 是ISR副本中同步消息最慢的副本的LEO 的offset
Kafka 的复制机制既不是完全的同步复制,也不是单纯的异步复制; 使用ISR方式则有效的权衡了数据可靠性和性能之间的关系
对于生产者看来副本之间的同步是异步进行的,因为只要leader完成数据写入即代表写入成功,但是副本直接消息同步采用的是ISR
也就是leader会监督follower的数据同步,控制HW和OSR等标准来平衡数据可靠性和性能之间的关系
ISR方式通过监督划分HW和OSR损失了一部分性能,同步落后多的副本放到OSR丧失leader竞选,也保证了数据基本可靠,不会产生丢失过多数据在leader宕机情况下;
Partition分区设计
一个主题Topic下存在多个分区Partition;每个分区分布在不同的Broker上,同一个分区会包含所有的副本Replicas,所有每个分区都有leader提供读写服务
方便扩展 (应对日益增长的数据量)
提高并发 (多个消费者同时消费同一个Topic不同分区的数据)

在kafka中,如果某个topic有多个partition,producer又怎么知道该将数据发往哪个partition呢?kafka中有几个原则:
partition在写入的时候可以指定需要写入的partition,如果有指定,则写入对应的partition。
如果没有指定partition,但是设置了数据的key,则会根据key的值hash出一个partition。
如果既没指定partition,又没有设置key,则会轮询选出一个partition。
日志存储
Kafka 中的消息是以主题为基本单位进行归类的,各个主题在逻辑上相互独立。每个主题又可以分为一个或多个分区,分区的数量可以在主题创建的时候指定,也可以在之后修改。每条消息在发送的时候会根据分区规则被追加到指定的分区中,分区中的每条消息都会被分配一个唯一的序列号,也就是通常所说的偏移量(offset)

日志目录
日志文件对外就是一个文件夹的形式,每个分区都有一个log文件夹,log文件又分成了一个个logsegment文件
logsegment文件包含 .log文件和两个索引文件 .index 和 .timeindex
每个logsegment的大小都是一样的,但是消息量不一定一样
logsegement中的文件都是以基准偏移量来命名的,基准偏移就是log文件中的第一条消息的偏移量
消息只会追加到最新的logsegment中,也就是activesegment
日志索引
两个索引文件
偏移量索引文件 .index
时间戳索引文件 .timeindex
这两个索引文件中的索引都是稀疏索引
这样的索引结构并不能保证每个消息在索引文件中都有对应的索引项,每当写入一定量(由 broker 端参数 log.index.interval.bytes指定,默认值为4096,即4KB)的消息时,偏移量索引文件和时间戳索引文件分别增加一个偏移量索引项和时间戳索引项,增大或减小log.index.interval.bytes的值,对应地可以增加或缩小索引项的密度
索引文件都是单调递增的,使用二分法快速定位,如果索引项不在索引文件中返回小于指定偏移量最大的偏移量
保证消息不丢失
那producer在向kafka写入消息的时候,怎么保证消息不丢失呢?其实上面的写入流程图中有描述出来,那就是通过ACK应答机制;
acks 是生产者客户端中一个非常重要的参数,它涉及消息的可靠性和吞吐量之间的权衡。acks参数有3种类型的值(都是字符串类型)
acks=1。默认值即为1。生产者发送消息之后,只要分区的leader副本成功写入消息,那么它就会收到来自服务端的成功响应
acks=0。生产者发送消息之后不需要等待任何服务端的响应
acks=-1或acks=all。生产者在消息发送之后,需要等待ISR中的所有副本都成功写入消息之后才能够收到来自服务端的成功响应;




