Kafka学习

各部分的概述

Producer

生产者,负责创建和发送消息

Consumer

消费者,负责阅读和处理消息

Broker

可以看做是一个Kafka实例,负责存储,接收,发送消息

Topic

是在Broker中的一类数据的分类

Partition

Partition是Topic的物理切分,也就是分区,一个Partition相当于一个独立的通道一个独立的线程

一个Topic的多个Partition是可以在不同的Broker中运行的

工作流程

流程

每条消息的的结构:Key+Value

1、生产者发送消息,把消息发送给Broker,并且指定Topic,指定Key。

2、Broker接收到消息之后,根据Topic和Key,把消息追加写到指定Partition的末尾;消息写入成功后,就会拿到一个Offset偏移量,也就是这个消息在Partition的位置编号。

3、消费者读取消息,向Broker请求订阅某个Topic,消费者是主动向Broker询问:有没有新消息。(订阅以Topic为单位)

4、消费者处理完这批消息之后,告诉Broker:我已经看完了编号为xx的消息了。这个xx就是新的Offset,Broker会记录这个记录,重复3。

image-20251109163848521
image-20251109163848521

key

Key是分区路由,用来保证同一个Partition的顺序性。

指定Key:一般都是拿主键id来保障顺序性。

在不指定Key的情况下,分区策略就会变成:
早期版本是轮询(均匀的发送到Topic的所有Partition),新版本是粘性分区(生产者会尝试把连续的消息一直发给同一个Partition,直到满再换)

指定分区也可以有顺序,但是这样扩展性就没有了,而且写死分区ID会导致数据全都放在一个分区里,资源倾斜。

生产者

批量发送

不会每发送一条消息就发给broker的分区,在客户端内存中维护一个 缓冲区,满足下面这两个条件

1、达到设定的最大等待时间 (linger.ms)

2、积累的消息达到设定的批量大小 (batch.size)

消费者

消费进度管理

工作原理

整体是

Kafka通过发布/订阅(Publish/Subscribe)模型实现异步通信:

  • 生产者(Producer):将消息异步发送到指定主题(Topic)的分区(Partition),无需等待消费者确认。发送过程是非阻塞的,允许生产者快速处理下一个任务。
  • 存储层(Broker):消息被追加写入到磁盘上的Commit Log(日志文件),保证了消息的持久性顺序性
  • 消费者(Consumer):消费者组(Consumer Group)以拉取(Pull)模式从Broker中获取消息,并独立管理自己的消费位移(Offset)。消息的处理是独立且异步

幂等不丢失原理

生产者端的

使用同步发送(至少等待 Leader 确认)和配置 acks=all 结合幂等性事务机制,确保消息不丢失且不重复

机制/配置作用核心原理
消息确认机制 (acks)控制消息发送的可靠级别。
  • acks=0:发送即成功,可能丢失。
  • acks=1:等待 Leader 写入成功,可能丢失(Leader 宕机)。
  • acks=all (或 -1):等待所有 ISR 中的副本同步成功才返回成功,极大地保障不丢失
幂等性 (enable.idempotence=true)保证消息不重复启用后,生产者自带一个唯一的 PID(Producer ID)和序列号。Broker 根据 PID 和序列号来判断该消息是否已被写入,如果已被写入则直接丢弃,解决重试导致的重复问题
事务机制保证原子性写入确保跨多个分区、多条消息的发送要么全部成功,要么全部失败,是实现Exactly-Once语义的基础

消费者端的

场景机制与处理详细说明
保障不丢失手动提交位移(enable.auto.commit=false消费者只有在完成业务逻辑处理后,才手动调用 commitSync()commitAsync() 提交位移。如果在处理过程中宕机,位移未提交,重启后会从上一次成功提交的位移处开始消费,实现消息重试。
处理消息重复业务幂等性设计由于手动提交位移可能导致消息重复消费,消费者必须设计业务层的幂等性。如:使用数据库唯一约束,或使用消息中的业务唯一 ID(如订单号)在 Redis 或 DB 中进行去重判断。
处理消息失败死信队列当消费者多次重试(在业务代码中捕获异常并循环重试)后仍无法成功处理某条消息时,不应无限重试导致阻塞。正确的做法是:将该消息写入一个单独的“死信队列”主题(DLQ Topic),由专门的监控或人工介入处理,并提交当前失败消息的位移,让主流程继续。