Kafka
架构与消息模型
Kafka 是持久化的分布式事件流平台,常用于日志汇聚、异步解耦、数据管道和流处理。

- Broker:存储分区数据并处理生产、消费请求。
- Topic / Partition:Topic 是逻辑消息流,Partition 是存储和并行处理单元。
- Producer:按指定分区、消息 key 或分区器选择目标分区。
- Consumer Group:同组消费者分担分区,不同组独立消费;传统消费组内,一个分区同时只分配给一个消费者。
- Controller:维护元数据与分区领导关系。KRaft 使用 Raft 元数据仲裁组;Kafka 4.x 已移除 ZooKeeper 模式。
- Kafka Connect / Streams:分别负责外部系统连接和应用内流处理,不是 Broker 必须附带的组件。

消息包含 key、value、timestamp、headers 等信息。每个分区内的 offset 单调递增,但不保证连续;消息顺序只在单个分区内成立。增加分区数可能改变 key 的分区映射,需评估同 key 顺序要求。
消费者提交的 offset 表示下一条待消费的位置。消息保留由时间、空间或日志压缩策略决定,与是否被消费无关。cleanup.policy=compact 保留每个 key 的最新状态,不能当作普通事件归档策略。
副本数不等于能无条件容忍的故障数。可用性还取决于 ISR、min.insync.replicas、leader 选举策略和 KRaft quorum;不要开启非同步副本选主来换取未评估的数据丢失。
Docker Compose 单节点实验
下面使用固定的 Kafka 3.9.1 KRaft 镜像,Broker 与 Controller 合并运行,适合本机验证。生产应选择经过兼容测试且仍受支持的补丁版本,并部署独立故障域与多个控制节点。
保存为 compose.yaml:
services:
kafka:
image: apache/kafka:3.9.1
hostname: kafka
ports:
- "127.0.0.1:9092:9092"
environment:
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_LISTENERS: INTERNAL://:29092,EXTERNAL://:9092,CONTROLLER://:9093
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:29092,EXTERNAL://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_LOG_DIRS: /var/lib/kafka/data
volumes:
- kafka-data:/var/lib/kafka/data
volumes:
kafka-data:
docker compose config -q
docker compose up -d
docker compose logs --tail=100 kafka
docker compose exec kafka /opt/kafka/bin/kafka-topics.sh \
--bootstrap-server kafka:29092 --create \
--topic quickstart-events --partitions 3 --replication-factor 1
printf 'first event\nsecond event\n' | docker compose exec -T kafka \
/opt/kafka/bin/kafka-console-producer.sh \
--bootstrap-server kafka:29092 --topic quickstart-events
docker compose exec kafka /opt/kafka/bin/kafka-console-consumer.sh \
--bootstrap-server kafka:29092 --topic quickstart-events \
--group demo --from-beginning --max-messages 2
容器内客户端使用 kafka:29092,宿主机客户端使用 localhost:9092。远程客户端需要同时修改端口绑定、防火墙和 EXTERNAL 通告地址,并配置 TLS/SASL;只修改监听地址不能解决返回元数据后的连接失败。保留数据卷,不要用删除卷来处理普通启动故障。
消费语义与可靠性
- 生产集群常用 3 副本、
min.insync.replicas=2、acks=all,并显式启用生产者幂等;ISR 不足时写入失败是保护行为。 - 生产者幂等可避免客户端重试在 Kafka 内造成重复,但不替代业务去重;消费者应在业务处理成功后提交 offset。
- 先提交再处理可能丢消息,先处理再提交可能重复。数据库写入应使用幂等键、唯一约束或可靠事务边界。
- Kafka 事务结合
isolation.level=read_committed可覆盖 Kafka 内的读写链路,不能自动保证外部数据库或 HTTP 调用恰好执行一次。 - 批量、压缩、
linger.ms与batch.size影响吞吐和延迟;按真实消息大小、峰值和延迟目标测试。
常用管理与排障
在以下命令中,kafka:29092 是本例容器内地址,生产环境添加认证配置文件参数。
docker compose exec kafka /opt/kafka/bin/kafka-topics.sh \
--bootstrap-server kafka:29092 --describe --topic quickstart-events
docker compose exec kafka /opt/kafka/bin/kafka-consumer-groups.sh \
--bootstrap-server kafka:29092 --describe --group demo
docker compose exec kafka /opt/kafka/bin/kafka-metadata-quorum.sh \
--bootstrap-server kafka:29092 describe --status
重置消费位点前停止组内消费者,先用 --dry-run 查看计划,再明确使用 --execute。重置可能导致重复处理或跳过消息,必须记录原位点和业务补偿方式。
| 现象 | 检查方向 |
|---|---|
| bootstrap 地址可连但生产/消费超时 | 检查每个 Broker 的 advertised.listeners、DNS、证书和网络路由 |
| 消费 lag 持续增长 | 检查处理耗时、分区倾斜、rebalance、批量和下游数据库;超过分区数再加消费者不会增加该组并行度 |
| 分区副本不足 | 检查 Broker 状态、磁盘、网络与 ISR;不要直接降低可靠性参数掩盖故障 |
| 消息过期无法消费 | 检查保留时间、保留容量和消费停机窗口,按业务恢复或重放 |
| 经常 rebalance | 检查 max.poll.interval.ms、处理批量、心跳、发布频率和成员变动 |
Prometheus 监控
Kafka exporter 主要提供分区和消费组指标;Broker JVM、请求延迟和控制器指标需另外通过 JMX exporter 等采集。Blackbox exporter 只做探测,不能替代 Kafka 协议和消费组监控。
scrape_configs:
- job_name: kafka-exporter
static_configs:
- targets: ["192.0.2.10:9308"]
| 常见 exporter 指标 | 含义 |
|---|---|
kafka_brokers |
Broker 数量 |
kafka_topic_partitions |
Topic 分区数 |
kafka_topic_partition_current_offset |
分区最新 offset |
kafka_topic_partition_oldest_offset |
分区最旧 offset |
kafka_topic_partition_in_sync_replica |
ISR 副本数量 |
kafka_topic_partition_under_replicated_partition |
分区是否副本不足 |
kafka_consumergroup_current_offset |
消费组已提交位点 |
kafka_consumergroup_lag |
消费组相对日志末尾的消息条数差 |
指标名与标签以实际 exporter 版本的 /metrics 为准。Lag 是条数差,不是时间延迟;无提交记录的组和未发现的组也不一定有时序。告警同时覆盖抓取失败、离线分区、ISR 缩减、磁盘水位、控制器 quorum、消费延迟与业务端到端延迟。
安全、升级与备份
生产使用 TLS、SASL 和 Topic/Group ACL,管理凭据与业务凭据分离。跨不可信网络不使用 PLAINTEXT。保留策略、ACL、Topic 配置和集群元数据纳入配置备份;副本不能替代异地恢复或业务归档。
滚动升级按官方版本路径操作,先检查客户端协议兼容、ISR 和 quorum,再逐节点升级。ZooKeeper 到 KRaft 的迁移只在支持迁移的版本和流程内执行,不能直接拿 ZooKeeper 配置启动 Kafka 4.x。
评论