3、Apache Kafka深度实践:Kafka架构与核心概念、分区与副本机制、生产者与消费者API、Kafka Connect与Schema Registry
聊到实时数据湖,Kafka 几乎是绕不开的组件。我个人习惯把它比作整个数据管道的心脏——数据从四面八方涌进来,经过它分流、缓冲,再被下游系统消费。今天我们就来深入拆解 Kafka 的核心机制。
3.1 Kafka 架构与核心概念
Kafka 的架构其实不复杂。说白了,就是一个分布式的「发布-订阅」消息系统。但它的设计思路跟传统消息队列(比如 RabbitMQ)很不一样。
核心角色就这几个:
- Producer:消息的发送方。我负责把数据扔进 Topic。
- Consumer:消息的接收方。从 Topic 里拉取数据。
- Broker:Kafka 集群中的一台服务器。负责存储消息。
- Topic:消息的逻辑分类。好比数据库里的表。
- Partition:Topic 的物理分片。这是 Kafka 高吞吐的关键。
- Offset:消息在 Partition 内的唯一编号。Consumer 靠它定位消费位置。
嗯,这里要注意:Kafka 不保证跨 Partition 的消息顺序。如果你需要严格有序,得把相关消息发到同一个 Partition 里。
核心设计理念:Kafka 把消息持久化到磁盘,利用顺序读写和零拷贝技术,实现了惊人的吞吐量。我见过单台 Broker 扛住百万级消息/秒的场景。
下面这张图展示了 Kafka 的整体架构和数据流向:
3.2 分区与副本机制
分区是 Kafka 实现水平扩展的基石。一个 Topic 可以拆成多个 Partition,每个 Partition 可以独立读写。你想想看,如果只有一个 Partition,那吞吐量就受限于单台机器的磁盘 IO。分而治之,吞吐量就上去了。
副本机制则是为了高可用。每个 Partition 可以有多个副本,其中一个是 Leader,其余是 Follower。生产者只往 Leader 写,消费者也只从 Leader 读。Follower 负责同步数据。
我的经验:我曾经在生产环境遇到过 Broker 宕机,因为副本数配置为 3,ISR(In-Sync Replicas)里还有两个副本,Leader 自动切换到 Follower,整个过程对业务完全透明。这就是副本的价值。
副本相关的几个关键参数:
| 参数 | 说明 | 推荐值 |
|---|---|---|
| replication.factor | 副本总数 | 3(生产环境) |
| min.insync.replicas | 最小 ISR 数量 | 2 |
| acks | 生产者确认级别 | all(配合 min.insync.replicas) |
避坑指南:我曾经遇到一个案例,某团队把 replication.factor 设为 2,min.insync.replicas 也设为 2。结果一台 Broker 宕机后,所有写入都失败了。因为 ISR 只剩 1 个,不满足最小要求。所以 replication.factor 至少要比 min.insync.replicas 大 1。
3.3 生产者与消费者 API
生产者的核心是 KafkaProducer。我个人习惯在初始化时重点配置三个东西:bootstrap.servers、key.serializer、value.serializer。
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("retries", 3);
props.put("batch.size", 16384);
props.put("linger.ms", 5);
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
// 发送消息
producer.send(new ProducerRecord<>("my-topic", "key1", "value1"));
producer.close();
消费者这边,核心是 KafkaConsumer。关键参数是 group.id——同一个 group 内的消费者共同消费一个 Topic,每条消息只被 group 内的一个消费者处理。
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "my-group");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("my-topic"));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
System.out.printf("offset = %d, key = %s, value = %s%n",
record.offset(), record.key(), record.value());
}
}
关键点:消费者是 pull 模式,不是 push。这意味着消费者自己控制消费速度。如果处理不过来,可以调大 poll 的间隔或者增加消费者数量。
3.4 Kafka Connect 与 Schema Registry
Kafka Connect 是 Kafka 的数据集成工具。说白了,它让你不用写代码就能把数据从外部系统(比如数据库、文件系统)导入 Kafka,或者从 Kafka 导出到外部系统。
Connect 有两种模式:
- Source Connector:从外部系统读取数据,写入 Kafka。
- Sink Connector:从 Kafka 读取数据,写入外部系统。
举个例子,用 JDBC Source Connector 把 MySQL 数据实时同步到 Kafka:
{
"name": "mysql-source-connector",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector",
"connection.url": "jdbc:mysql://localhost:3306/mydb",
"connection.user": "root",
"connection.password": "password",
"topic.prefix": "mysql-",
"table.whitelist": "orders,users",
"mode": "incrementing",
"incrementing.column.name": "id"
}
}
Schema Registry 解决的是数据格式一致性问题。你想想看,如果 Producer 发的是 JSON,Consumer 却按 Avro 解析,那肯定出乱子。Schema Registry 统一管理所有 Topic 的数据 schema,确保生产者和消费者使用相同的协议。
我的建议:在金融场景中,数据格式的兼容性至关重要。我曾经遇到一个事故,某个团队修改了 Avro schema 的字段类型,导致下游消费反序列化失败。用了 Schema Registry 后,可以通过兼容性检查(比如 BACKWARD、FORWARD)提前发现这类问题。
Schema Registry 支持多种兼容性策略:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| BACKWARD | 新 schema 可以读取旧数据 | 消费者先升级 |
| FORWARD | 旧 schema 可以读取新数据 | 生产者先升级 |
| FULL | 同时支持前后兼容 | 生产者和消费者同时升级 |
| NONE | 不检查兼容性 | 开发测试环境 |
嗯,到这里 Kafka 的核心内容就差不多了。记住一点:Kafka 不是银弹,但它确实是构建实时数据湖的最佳基础设施之一。理解它的分区、副本、生产消费模型,你就能在项目中游刃有余。
公众号:蓝海数据掘金营,微信 deep3321