kafka教程
Kafka 中Producer采用push模型而Consumer采用pull模型。TopicTopic主题是消息的逻辑分类或通道。它是Kafka中用于组织和存储消息的基本单元。一个Topic可以被看作是一个消息发布的地方生产者将消息发布到一个特定的Topic而消费者则订阅一个或多个Topic以接收消息。Consumer groupConsumer Group消费者组 为了扩展消费者并实现并行处理多个消费者可以组成一个消费者组。每个分区只能由消费者组内的一个消费者处理这样可以确保消息在每个分区内的有序处理。每个消费者组都有一个组id同一个消费组者的消费者可以消费同一topic下不同分区的数据但是不会组内多个消费者消费同一分区的数据。在实际的应用中建议消费者组的consumer的数量与partition的数量一致Partition每个topic可以有多个分区每个分区中的消息是有序的。生产者将消息发布到topic时Kafka会根据一定的策略将消息分配到不同的分区。消费者可以订阅整个topic也可以选择订阅topic的特定partition。每个topic可以划分为一个或多个partition分区是Kafka中的基本存储单元。分区允许水平扩展每个分区可以独立地分布在不同的机器上提高了Kafka的伸缩性和性能。那么当Producer将消息发送给broker分区的原因提高吞吐量 分区允许Kafka集群并行处理消息。每个分区都是一个独立的有序队列多个分区可以同时进行读写操作使得整个系统能够更有效地处理大量的消息。这种并行性是Kafka实现高吞吐量的关键。实现水平扩展 通过将消息分布在多个分区上Kafka可以轻松地在集群中添加更多的Broker来实现水平扩展。每个Broker只需要负责一部分分区从而有效地分担了负载。这种扩展性使得Kafka能够适应不断增长的数据量和流量。容错性 每个分区的数据都可以有多个副本Replica在集群的不同Broker上存储。如果某个Broker或分区发生故障其他副本依然可用。这种冗余机制提高了系统的容错性确保了数据的可用性和持久性。有序性 分区内的消息是有序的而分区间的消息不做有序保证。这使得Kafka在保持消息的有序性的同时可以在不同的分区上实现并行处理使系统更加灵活。提供灵活的消息处理模型 分区允许消费者以消费者组的形式协同处理消息。每个分区只能被同一个消费者Parition的副本replice为了提高可靠性和容错性每个分区可以有多个副本replica。这些副本分布在不同的Broker上确保即使其中一个Broker失效仍然有其他副本可用。BrokerBroker是一个独立的Kafka服务器实例负责处理消息的生产和消费。存储 Broker存储了消息的持久化副本以确保消息的持久性。每个Topic的分区被分布在不同的Broker上以实现分布式存储和水平扩展。Leader和Follower 对于每个Topic的分区一个Broker被选举为Leader其余的为Follower。Leader负责处理读写请求而Follower则同步Leader的数据以提供容错和冗余。消息的生产和消费 生产者将消息发送到Topic而消费者从Topic中消费消息。Broker协调这两个过程确保消息被正确地传递给订阅了相应Topic的消费者。Broker负责存储和管理所有Topic的Partition数据并协调Partition之间的数据同步和复制。Producer将消息发送给broker的过程选择 Topic 生产者选择一个或多个目标 Topic。选择分区 如果生产者选择将消息发送到特定的分区它可以指定分区否则Kafka 会使用一种策略例如轮询或哈希来决定将消息发送到哪个分区。构造消息 生产者构造要发送的消息这可以是文本、二进制数据等。发送消息 生产者将消息发送给 Kafka 集群中的 Broker。生产者需要知道 Broker 的地址通常至少提供一个 Broker 的地址然后将消息发送给指定的 Topic 和分区。Producer选择发送的分区过程partition在写入的时候可以指定需要写入的partition如果有指定则写入对应的partition。如果没有指定partition但是设置了数据的key则会根据key的值hash出一个partition。如果既没指定partition又没有设置key则会轮询选出一个partition。Kafka将数据顺序存储在磁盘上Kafka既将数据写入磁盘也在内存中进行一些操作。Kafka的设计目标之一是提供持久性和高吞吐量。因此它会将消息写入磁盘以确保数据的持久性这使得即使在Broker重启后数据仍然可用。具体来说Kafka使用了一种称为写入日志write-ahead log的机制。当消息被生产者发布到一个Topic时Kafka首先将消息追加到该Topic的日志文件中。这些日志文件通常位于磁盘上。写入日志的方式使得消息的添加成为原子操作并且消息按顺序写入。同时Kafka还利用内存来提高性能。在Broker内Kafka会维护一个称为Page Cache的内存区域用于缓存最近使用的数据块。这使得在读取数据时可以在内存中快速获取提高读取性能。日志段Partition在服务器上的表现形式就是一个一个的文件夹存储在磁盘上每个partition的文件夹下面会有多组segment文件每个segment文件中又包含.index文件、.log文件、.timeindex文件三个文件。每个日志段包含三个主要文件.log 文件 这个文件是实际存储消息的地方。消息以追加的方式写入这个文件并且按顺序存储。这种追加写入的方式使得写入操作是高效的同时也有助于提高读取性能。.index 文件 这个文件是索引文件用于快速定位消息。它包含消息的物理偏移offset和消息的逻辑偏移相对于分区的偏移之间的映射。索引文件的存在使得 Kafka 能够更有效地执行消息的检索操作而不必扫描整个日志文件。.timeindex 文件 这个文件是时间索引文件在某些版本的 Kafka 中引入。它提供了消息时间戳和物理偏移之间的映射以支持按时间范围检索消息。每个分区由多个这样的日志段组成。当一个日志段达到一定的大小或者时间限制时Kafka会创建一个新的日志段。这种机制有助于管理磁盘空间同时也有利于日志的压缩和维护。查找消息的时候是怎么利用segmentoffset配合查找的呢假如现在需要查找一个offset为368801的message是什么样的过程呢我们先看看下面的图1、 先找到offset的368801message所在的segment文件利用二分法查找这里找到的就是在第二个segment文件。2、 打开找到的segment中的.index文件也就是368796.index文件该文件起始偏移量为3687961我们要查找的offset为368801的message在该index内的偏移量为3687965368801所以这里要查找的相对offset为5。由于该文件采用的是稀疏索引的方式存储着相对offset及对应message物理偏移量的关系所以直接找相对offset为5的索引找不到这里同样利用二分法查找相对offset小于或者等于指定的相对offset的索引条目中最大的那个相对offset所以找到的是相对offset为4的这个索引。3、 根据找到的相对offset为4的索引确定message存储的物理偏移位置为256。打开数据文件从位置为256的那个地方开始顺序扫描直到找到offset为368801的那条Message。这套机制是建立在offset为有序的基础上利用segment有序offset稀疏索引二分查找顺序查找等多种手段来高效的查找数据消费者组同一个 Group 代表“这些消费者共同完成一个消费任务”所以他们跑的service是完全一致的存在的意义就是能够随便地动态扩容。Consumer Group 是消费逻辑的一个集合一个 Group 可以消费一个或多个 Topic同一个 Group 内的消费者通常运行相同代码通过分担 Partition 来提高吞吐一个 Consumer 可以消费多个 Partition但一个 Partition 在同一个 Group 内只能被一个 Consumer 消费是否指定 Partition可以通过 subscribe 自动分配也可以 assign 手动指定。3 Partition5 Consumer多余 Consumer 会一直空闲。Consumer Partition 时多余 Consumer 会长期空闲直到 Partition 增加、消费者变化或换 Group。Kafka 的消费并行度上限由 Partition 数量决定而不是 Consumer 数量。Producer 的幂等用PID实现kafka侧的防重防止重复投递。3 Partition2 Consumer 分配后正常情况下会保持这个分配关系。C1 一直负责消费 P0、P1C2 一直负责消费 P2除非rebalanceC3 加入Kafka 触发 RebalanceC1 - P0 C2 - P1 C3 - P消费者加入后rebalance给消费者分配好分区以后消费者主动去对应的分区去拉取消息Offset消息在 Partition 中的位置。生产者发送消息1.指定key然后hash获得分区2.指定分区3.轮询一个 Partition 内的消息可以被多个 Consumer Group 同时消费Kafka 的 offset 是以 Consumer Group 为单位保存的。kafka不会消息消费完成后就删除消息而是等待达到配置的大小阈值或者存活时间。一个分区同时只能由一个消费者组内的一个消费者实例消费但是可以被多个不同消费者组消费。因为不同消费者组的offset不同。所以他是发布订阅模式。消息从生产到消费的完整生命周期保证可靠性1.生产者需要等待kafka返回ack有三种直接返回等待leader存储完成返回同步foller返回。2.防止返回的ack丢失从而重复生成消息到kafkakafka有生产端防重PID。3.kafka存储通过follower备份从而实现可靠性4.Kafka 消费不是删除消息。而是记录 offset。记录offset是由消费者返回offset然后记录的可以开启手动提交offset。5.如果offset提交丢失那么消费者会重复消费所以kafka是保证至少消费一次不保证只能消费一次。6.所以为了实现消费者只消费一次那么消费者必须保证幂等消费。