kafka:【2】工作原理

kafka工作流程

kafka中消息是以topic进行分类的,topic是数据的主题,生产者是生产消息,消费者是消费消息,中间都需要topic。

topic是逻辑上的概念,而物理概念的是partition,broker(服务器)中可以有一个或多个partition,一个partition对应于一个log文件,log文件用来存储生产者的数据,生产者生产的数据会不断追加到log文件的末端,且每天数据都有自己的offset(偏移量)。消费者组中的每个消费者,消费指定分区的数据,实时记录自己消费的offset,防止出错时恢复,从上次消费位置继续消费。

kafka文件存储

生产者生产的消息会不断追加到log文件末尾,这个顺序不会打乱,官网数据说,同样的磁盘,顺序写能到600M/s,而随机写只有100k/s,之所以写的这么快,是因为顺序写,省去了大量磁头寻址的时间,从而实现高效读写。

实际存储使用log文件,当然不能一直往里存,kafka采用了分片和索引机制,每个partition又分为多个segment file,每个segment对应两个文件,即.log和.index文件。

  • .index:文件存储大量索引信息
  • .log:文件存储大量的数据
    索引文件中的元数据指向对应log文件中message的物理偏移地址

kafka的分区

为什么要分区

  1. 易于集群扩展:分区机制使得Topic的数据可以被"切分"成多个部分,存储在不同的服务器(Broker)上。
    • 存储扩展:一个Topic的数据量可能远超单个服务器的磁盘容量。通过分区,可以将Topic的数据分散到整个集群,理论上Topic的容量只受限于集群的总磁盘空间。
    • 负载均衡 :读写请求会被分散到持有不同分区的多个Broker上,避免了单一服务器的I/O、CPU和网络瓶颈。当集群负载增加时,我们只需向集群中添加新的Broker服务器,并将部分分区迁移过去,即可线性地扩展整个集群的处理能力。
      场景举例:假设一个Topic每秒产生1GB的数据,单台服务器无法承受如此高的写入负载。如果我们将该Topic设置为10个分区,并将它们分布在10台不同的Broker上,那么每台Broker平均只需处理每秒100MB的写入请求,使得系统可以轻松应对
  2. 提高并发:并发体现在生产者(Producer)和消费者(Consumer)两端。
    • 生产者并发写入:生产者可以同时向多个分区发送消息。例如,发往Partition-0的请求和发往Partition-1的请求可以由不同的Broker并行处理,从而极大地提高了消息的写入速度。
    • 消费者并行处理:这是分区的核心优势。在同一个消费者组(Consumer Group)内,Kafka允许不同的消费者实例同时消费不同的分区。如果一个Topic有10个分区,那么一个消费者组最多可以有10个消费者实例来并行处理消息,每个消费者负责一个分区。这使得消息的处理能力可以随着消费者数量的增加而横向扩展,从而实现高吞-吐量。最大并行度=分区数量
  3. 提供数据冗余和高可用性:分区是Kafka实现容灾和高可用的基础单元。每个分区都可以配置多个副本(Replica),这些副本存储在不同的Broker上。
  4. 保证消息的顺序性:分区在提供高并发的同时,也提供了一种局部有序性的保证。
    • 分区内有序 :Kafka只保证在单个分区内的消息是有序的。也就是说,生产者按照A、B、C的顺序发送到同一个分区的消息,消费者也一定会按照A、B、C的顺序来消费它们。
    • 分区之间无序:但是,Kafka不保证Topic级别的全局消息顺序。发往Partition-0的消息和发往Partition-1的消息,它们的消费顺序是无法保证的。

分区的原则

producer将发送的数据封装成ProducerRecord对象。有以下3中分区原则:

  1. 指明partition值的情况下:直接将指明的值直接作为partiton值
  2. 没有指明partition值,但有key的情况下:将key的hash值与topic的partition数进行取余得到partition值
  3. 即没有partition值,又没有key值的情况下:第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与topic可用的partition总数取余得到partition值,也就是常说的round-robin算法。

数据可靠性保证

ack

为了保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到来自producer的消息,都需要向producer发从ack(acknowledgement),以确认收到,如果producer收到ack,就会进行下一轮的发送,否则重新发送数据。

副本同步策略:

方案 优点 缺点
半数以上完成同步,就发送ack 延迟低 选举新的leader时,容忍n台节点的故障,需要2n+1个副本
全部完成同步,才发送ack 选举新的leader时,容忍n台节点故障,需要n+1个副本 延迟高

kafka选择使用第二种方案,因为第二种方案虽然延迟有些高,但对kafka影响非常小,而这样会减少服务器的数量,避免的数据大量冗余,也就是说降低了成本

ISR

采用第二种方案后,如果leader收到数据后,follower开始同步数据,但其中一个迟迟不能与leader同步,那leader就得一直等下去,直到同步完,才能发送ack。

面对这样的问题,leader维护了一个动态的in-sync replica set (ISR),意为和leader保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader就会给follower发送ack。

如果follower长时间未向leader同步数据,则该follower将被踢出ISR,该时间阈值由replica.lag.time.max.ms参数设定。

如果Leader发生故障之后,就会从ISR中选举新的leader,之后,为保证多个副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader同步数据。

消费方式

消费者的消费方式采用pull(拉)的方式从broker中读取数据

push模式是消息的发送速率由broker决定,目标是尽可能以最快速度传递消息,这样会引发一个问题,即消费者可能来不及处理消息,典型的表现就是拒绝服务以及网络拥堵。

而pull方式,则是由消费者来决定消息传递的速率,但也是有不足之处,如果kafka没有数据,消费者可能会陷入循环,一直返回空数据。kafka 为了解决这个问题,消费数据时会传入一个时长参数timeout,如果没有数据可以消费,消费者会等待一段时间后再返回,这段时长就是timeout。

分区分配策略

一个consumer group中有多个consumer,一个 topic有多个partition,所以必然会涉及到partition的分配问题,即确定那个partition由哪个consumer来消费。

Kafka有两种分配策略:RoundRobin(轮询)和Rang(范围)
RoundRobin策略

  • 将所有主题的分区按字典序排序,然后通过轮询方式分配给消费者组中的各个消费者
  • 这种分配方式比较均衡,能确保每个消费者获得大致相同数量的分区
  • 适用于消费者处理能力相近的场景,可以实现负载均衡

Range策略

  • 按主题逐个分配,对每个主题的分区按范围划分给消费者
  • 例如,某个主题有10个分区,3个消费者,则可能分配为:消费者1(0-3),消费者2(4-6),消费者3(7-9)
  • 可能导致分配不均衡,特别是当分区数不能被消费者数整除时
  • 但这种策略能保证同一主题的分区连续分配,有利于局部性处理

offset(偏移量)维护

由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置的继续消费,所以consumer需要实时记录自己消费到了哪个offset,以便故障恢复后继续消费。

相关推荐
励志成为糕手2 小时前
Kafka架构:构建高吞吐量分布式消息系统的艺术
分布式·架构·kafka·消息中间件·数据流处理
小句3 小时前
RabbitMQ对接MQTT消息发布指南
分布式·rabbitmq·ruby
xiaofan6720133 小时前
2025在校大学生可以考哪些大数据专业证书?
大数据
u0104058363 小时前
霸王餐返利app的分布式架构设计:基于事件驱动的订单处理系统
分布式
gooxi_hui3 小时前
8卡直连,Turin加持!国鑫8U8卡服务器让生成式AI落地更近一步
大数据·人工智能
程序员小羊!4 小时前
大数据电商流量分析项目实战:Hive 数据仓库(三)
大数据·数据仓库·hive
JAVA学习通4 小时前
【RabbitMQ】高级特性:持久性·发送方确认·重试机制·TTL·死信队列·延迟队列·事务·消息分发
分布式·rabbitmq
海阔天空在前走4 小时前
MQ防止重复消费的四种方法
分布式·rabbitmq
专注API从业者4 小时前
Scrapy 集成 JD API:一种高效且合规的商品数据采集方案
大数据·数据库·scrapy