2、Kafka基础架构回顾:Producer、Broker、Consumer、Topic、Partition核心概念
好,咱们正式开始讲Kafka。在深入精准一次语义之前,我强烈建议先把地基夯实。你想想看,如果连Broker和Partition的关系都搞不清楚,后面聊事务和幂等性,那基本就是听天书。
这一节,我就带你快速过一遍Kafka的五大核心概念。嗯,说白了就是五个角色:Producer、Broker、Consumer、Topic、Partition。我会结合我在金融项目中踩过的坑,帮你把这些概念真正「焊死」在脑子里。
2.1 Topic:逻辑上的消息分类
Topic,你可以把它理解成一个「消息的类别」。比如我们做交易系统,会有「订单Topic」、「风控Topic」、「清算Topic」。每个Topic负责一类业务消息。
我个人习惯,在金融系统里给Topic命名时,会带上业务线和环境标识。比如:trade-order-prod、risk-alert-test。为什么?因为我在一个项目里见过有人把所有消息都塞到一个Topic里,结果排查问题的时候,日志刷得飞起,根本分不清哪条是订单、哪条是风控。嗯,那场面,相当混乱。
2.2 Partition:物理存储的最小单元
Partition才是Kafka真正干活的角色。每个Topic会被拆成多个Partition,每个Partition是一个有序的、不可变的日志文件。
为什么会这样设计?说白了就是为了并行。你想想看,如果只有一个Partition,那所有消息都得排队写入,性能肯定上不去。多Partition就能让多个Consumer同时消费,提升吞吐量。
我记得在做一个高并发支付系统时,订单Topic分了32个Partition。当时有个同事问:「为啥不分64个?」我告诉他,Partition不是越多越好。每个Partition对应一个文件句柄,太多Partition会导致Broker的元数据膨胀,反而拖慢性能。这个坑,我替你们踩过了。
| 属性 | 说明 |
|---|---|
| 有序性 | 每个Partition内部消息有序,但跨Partition不保证全局有序 |
| 不可变性 | 消息写入后不能修改,只能追加 |
| 偏移量 | 每条消息在Partition内有一个唯一的offset |
2.3 Broker:Kafka集群中的服务器节点
Broker就是运行Kafka服务的机器。一个集群由多个Broker组成,每个Broker可以管理多个Partition。
这里有个关键点:Broker是无状态的。什么意思?就是Broker本身不保存消费者的消费进度,消费进度由Consumer自己维护(或者通过Kafka内置的__consumer_offsets Topic保存)。
我曾经遇到过一个生产事故:某个Broker宕机了,结果整个集群的写入都变慢了。排查下来发现,那个Broker上恰好挂着某个热门Topic的Leader Partition。嗯,这里要提醒你:在生产环境中,一定要合理分配Partition的Leader副本,避免单点瓶颈。
2.4 Producer:消息的生产者
Producer负责把消息发送到指定的Topic。它可以选择把消息发到哪个Partition,也可以让Kafka自动分配。
在金融系统里,Producer的可靠性至关重要。我习惯在Producer端开启acks=all,确保消息被所有副本确认后才算发送成功。虽然会牺牲一点延迟,但换来了数据不丢失的保障。
另外,Producer还有一个重要的机制:幂等性。开启enable.idempotence=true后,Producer会为每条消息生成一个唯一的序列号,Broker端会去重。这个特性在精准一次语义中非常关键,后面我会详细讲。
// 一个典型的Producer配置示例
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("acks", "all");
props.put("enable.idempotence", true); // 开启幂等性
props.put("retries", Integer.MAX_VALUE); // 无限重试
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
2.5 Consumer:消息的消费者
Consumer从Topic拉取消息进行消费。它属于「拉模式」,也就是Consumer主动去Broker拉数据,而不是Broker推给Consumer。
为什么用拉模式?因为推模式容易把Consumer压垮。你想想看,如果Broker不管Consumer能不能处理,一股脑把消息推过来,Consumer的内存很快就爆了。拉模式让Consumer自己控制消费速度,更安全。
Consumer还有一个重要的概念:Consumer Group。同一个Group内的Consumer共同消费一个Topic,每个Partition只能被Group内的一个Consumer消费。这个机制保证了消息不会被重复消费。
我记得有一次,一个同事把两个服务的Consumer Group配置成了同一个名字,结果两个服务互相抢Partition,导致消息处理混乱。嗯,这种低级错误,咱们就别犯了。
2.6 核心关系图
下面这张图,我帮你把Producer、Broker、Consumer、Topic、Partition之间的关系梳理清楚了。你可以把它当作一个「速查地图」,以后遇到Kafka相关的问题,先看这张图,思路就清晰了。
这张图里,你可以看到消息的完整流转路径:Producer把消息发到Topic,Topic内部拆成多个Partition,Partition存储在Broker上,Consumer从Broker拉取消息进行消费。嗯,就是这么个流程。
好了,这一节的内容就到这里。Kafka的基础架构,说白了就是围绕这五个角色展开的。后面的章节,我们会基于这些概念,深入探讨精准一次语义的实现原理。你先把这些基础打牢,后面学起来会轻松很多。