一个典型的kafka集群包含若干Producer,若干个Broker(kafka支持水平扩展)、若干个Consumer Group,以及一个zookeeper集群。kafka通过zookeeper管理集群配置及服务协同。Producer使用push模式将消息发布到broker,consumer通过监听使用pull模式从broker订阅并消费消息。
多个broker协同工作,producer和consumer部署在各个业务逻辑中。三者通过zookeeper管理协调请求和转发。这样就组成了一个高性能的分布式消息发布和订阅系统。

图上有一个细节是和其他mq中间件不同的点,producer 发送消息到broker的过程是push,而consumer从broker消费消息的过程是pull,主动去拉数据。而不是broker把数据主动发送给consumer。
1、基本概念
Broker:Kafka集群包含一个或多个服务器,这种服务器被称为broker。broker端不维护数据的消费状态,提升了性能。直接使用磁盘进行存储,线性读写,速度快:避免了数据在JVM内存和系统内存之间的复制,减少耗性能的创建对象和垃圾回收。
Producer:消息的发送方负责发布消息到Kafka broker。
Consumer:消息消费者,向Kafka broker读取消息的客户端,consumer从broker拉取(pull)数据并进行处理。Consumer Group
每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group。
Topic:Kaka中的消息以主题为单位进行归类,生产者负责将消息发送到特定的主题(发送到 Kafka集群中的每条消息都要指定一个主题),而消费者负责订阅主题并进行消费。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)。
Partition:主题是一个逻辑上的概念,它还可以细分为多个分区,一个分区只属于单个主题。同一主题下的不同分区包含的消息是不同的,每个Partition在物理上对应一个文件夹,该文件夹下存储这个Partition的所有消息和索引文件,分区在存储层面可以看作一个可追加的日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset)。 offset是消息在分区中的唯一标识,Kafka通过它来保证消息在分区内的顺序性,不过 offset并不跨越分区,也就是说,Kaka保证的是分区有序而不是主题有序。
2、副本机制
Kafka为分区引入了多副本(Replica)机制,通过增加副本数量可以提升容灾能力。同分区的不同副本中保存的是相同的消息(在同一时刻,副本之间并非完全一样),副本之间是“一主多从”的关系,其中 leader副本负责处理读写请求, follower副本只负责与 leader副本的消息同步。副本处于不同的 broker中,当 leader副本出现故障时,从 follower副本中重新选举新的 leader副本对外提供服务。 Kafka通过多副本机制实现了故障的自动转移,当 Kafka集群中某个 broker失效时仍然能保证服务可用。

如图1-3所示, Kafka集群中有4个 broker,某个主题中有3个分区,且副本因子(即副本个数)也为3,如此每个分区便有1个 leader副本和2个 follower副本。生产者和消费者只与 leader副本进行交互,而 follower副本只负责消息的同步,很多时候 follower副本中的消息相对 leader副本而言会有一定的滞后。
Kafka消费端也具备一定的容灾能力。 Consumer使用拉(Pull)模式从服务端拉取消息,并且保存消费的具体位置,当消费者宕机后恢复上线时可以根据之前保存的消费位置重新拉取需要的消息进行消费,这样就不会造成消息丢失。
ISR与OSR
分区中的所有副本统称为AR(Assigned Replicas)。所有与 leader副本保持一定程度同步的副本(包括leader副本在内)组成ISR(In-Sync Replicas),ISR集合是AR集合中的一个子集。消息会先发送到 leader副本,然后 follower副本才能从 leader副本中拉取消息进行同步,同步期间内 follower副本相对于 leader副本而言会有一定程度的滞后。前面所说的“一定程度的同步”是指可忍受的滞后范围,这个范围可以通过参数进行配置。与 leader副本同步滞后过多的副本(不包括 leader副本)组成OSR(Out- of-Sync Replicas),由此可见,AR=ISR+OSR在正常情况下,所有的 follower副本都应该与 leader副本保持一定程度的同步,即AR=ISR,OSR集合为空。
leader副本负责维护和跟踪ISR集合中所有 follower副本的滞后状态,当 follower副本落后太多或失效时, leader副本会把它从ISR集合中剔除。如果OSR集合中有 follower副本“追上”了 leader副本,那么 leader副本会把它从OSR集合转移至ISR集合。默认情况下,当 leader副本发生故障时,只有在ISR集合中的副本才有资格被选举为新的 leader,而在OSR集合中的副本则没有任何机会(不过这个原则也可以通过修改相应的参数配置来改变)。
HW和LEO
ISR与HW和LEO也有紧密的关系。HW是 High Watermark的缩写,俗称高水位,它标识了一个特定的消息偏移量( offset,消费者只能拉取到这个 offset之前的消息。
如图1-4所示,它代表一个日志文件,这个日志文件中有9条消息,第一条消息的offset(LogStartOffset)为0,最后一条消息的 offset为8,offset为9的消息用虚线框表示,代表下条待写入的消息。日志文件的HW为6,表示消费者只能拉取到 offset在0至5之间的消息,
而 offset为6的消息对消费者而言是不可见的。

LEO是 Log End Offset的缩写,它标识当前日志文件中下一条待写入消息的offset,图1-4中 offset为9的位置即为当前日志文件的LEO,LEO的大小相当于当前日志分区中最后一条消息的ofet值加1分区ISR集合中的每个副本都会维护自身的LEO,而ISR集合中最小的LEO即为分区的HW,对消费者而言只能消费HW之前的消息。
为了让读者更好地理解ISR集合,以及HW和LEO之间的关系,下面通过一个简单的示例来进行相关的说明。如图1-5所示,假设某个分区的ISR集合中有3个副本,即一个 leader副本和2个 follower副本,此时分区的LEO和HW都为3。消息3和消息4从生产者发出之后会被先存入 leader副本,如图1-6所示。


在消息写入 leader副本之后, follower副本会发送拉取请求来拉取消息3和消息4以进行消息同步。
在同步过程中,不同的 follower副本的同步效率也不尽相同。如图1-7所示,在某一时刻follower完全跟上了 leader副本而 follower2只同步了消息3,如此 leader副本的LEO为5,follower的LEO为5, follower2的LEO为4,那么当前分区的HW取最小值4,此时消费者可
以消费到 offset为0至3之间的消息。
写入消息(情形4)如图1-8所示,所有的副本都成功写入了消息3和消息4,整个分区的HW和LEO都变为5,因此消费者可以消费到 offset为4的消息了。


由此可见,Kaka的复制机制既不是完全的同步复制,也不是单纯的异步复制。事实上,同步复制要求所有能工作的 follower副本都复制完,这条消息才会被确认为已成功提交,这种复制方式极大地影响了性能。而在异步复制方式下, follower副本异步地从 leader副本中复制数据,数据只要被 leader副本写入就被认为已经成功提交。在这种情况下,如果 follower副本都还没有复制完而落后于 leader副本,突然 leader副本宕机,则会造成数据丢失。 Kafka使用的这种ISR的方式则有效地权衡了数据可靠性和性能之间的关系。
361

被折叠的 条评论
为什么被折叠?



