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。
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) | 控制消息发送的可靠级别。 |
| |
幂等性 (enable.idempotence=true) | 保证消息不重复。 | 启用后,生产者自带一个唯一的 PID(Producer ID)和序列号。Broker 根据 PID 和序列号来判断该消息是否已被写入,如果已被写入则直接丢弃,解决重试导致的重复问题。 | |
| 事务机制 | 保证原子性写入。 | 确保跨多个分区、多条消息的发送要么全部成功,要么全部失败,是实现Exactly-Once语义的基础 |
消费者端的
| 场景 | 机制与处理 | 详细说明 |
|---|---|---|
| 保障不丢失 | 手动提交位移(enable.auto.commit=false) | 消费者只有在完成业务逻辑处理后,才手动调用 commitSync() 或 commitAsync() 提交位移。如果在处理过程中宕机,位移未提交,重启后会从上一次成功提交的位移处开始消费,实现消息重试。 |
| 处理消息重复 | 业务幂等性设计 | 由于手动提交位移可能导致消息重复消费,消费者必须设计业务层的幂等性。如:使用数据库唯一约束,或使用消息中的业务唯一 ID(如订单号)在 Redis 或 DB 中进行去重判断。 |
| 处理消息失败 | 死信队列 | 当消费者多次重试(在业务代码中捕获异常并循环重试)后仍无法成功处理某条消息时,不应无限重试导致阻塞。正确的做法是:将该消息写入一个单独的“死信队列”主题(DLQ Topic),由专门的监控或人工介入处理,并提交当前失败消息的位移,让主流程继续。 |

