文章目录前言一、Kafka 的架构设计1. Producer生产者2. Broker代理节点3. Topic主题4. Partition分区5. Consumer消费者6. Consumer Group消费者组7. Replica副本8. Controller控制器9. Zookeeper二、Kafka 的优缺点优点缺点三、Kafka 的应用场景场景一异步处理与服务解耦场景二日志收集与聚合场景三流量削峰场景四实时数据流处理场景五网站活动跟踪场景六事件溯源与审计日志场景七数据中转枢纽前言大家好我是无籽西瓜。这是「西瓜带你学Kafka」专栏的第一篇文章。说起 Kafka很多人的第一反应是消息队列。没错但又不完全对——它更像是一个分布式的流处理平台消息队列只是它的能力之一。在实际工作中不管你是做后端开发、大数据还是架构设计Kafka 几乎是绕不开的基础设施。异步解耦要用它日志收集要用它实时计算还是要用它。但很多人对 Kafka 的理解停留在会用 API 收发消息的层面一旦遇到消息丢失、消费积压、分区再均衡这些问题就容易懵。所以我打算写这个专栏从架构设计到核心原理从基础使用到生产实战一步步把 Kafka 讲透。不堆概念不贴官方文档翻译尽量用大白话和代码示例把每个知识点说清楚。一、Kafka 的架构设计先来一张全局视角看看 Kafka 的核心组件是怎么协作的。1. Producer生产者Producer 是消息的源头负责将消息发布到 Kafka 集群。它可以是任何终端或服务——比如你的订单系统、日志采集器、埋点 SDK 等。Producer 发送消息时需要指定目标 Topic也可以选择性地指定 Partition。如果不指定 PartitionKafka 会根据 key 的哈希值或轮询策略自动分配。// Producer 示例发送消息到指定 TopicPropertiespropsnewProperties();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);KafkaProducerString,StringproducernewKafkaProducer(props);// 发送一条消息到 order-topicproducer.send(newProducerRecord(order-topic,orderId-1001,下单成功));producer.close();2. Broker代理节点一个 Kafka 节点就是一个 Broker多个 Broker 组成一个 Kafka 集群。Broker 负责接收 Producer 的消息、存储消息、并为 Consumer 提供消费服务。Partition 在 Broker 上的分布规则是理解 Kafka 集群的关键这里分三种情况场景Partition 数Broker 数分布情况均匀分布nn每个 Broker 存储 1 个 Partition完美均衡Broker 富余nm n (m 0)只有 n 个 Broker 会存储 Partition其余 m 个 Broker 空闲Broker 不足n n部分 Broker 存储多个 Partition应尽量避免会导致数据不均衡3. Topic主题Topic 是 Kafka 中消息的逻辑分类。每条发布到 Kafka 的消息都归属于某个 Topic。你可以把 Topic 理解为数据库中的表——Kafka 是面向 Topic 的。比如电商系统中你可能会创建这些 Topicorder-topic订单相关消息payment-topic支付相关消息log-topic系统日志Producer 往指定 Topic 发消息Consumer 从指定 Topic 消费消息Topic 是两者之间的桥梁。4. Partition分区Partition 是 Topic 在物理上的分区一个 Topic 可以分为多个 Partition。每个 Partition 是一个有序的、不可变的记录序列消息被追加写入时会分配一个递增的 offset。重点单个 Partition 内的消息是有序的但跨 Partition 无法保证全局有序。这也是 Kafka 高吞吐的核心秘密之一——通过分区实现并行读写。5. Consumer消费者Consumer 从 Kafka 集群中拉取消息进行消费。与很多消息队列的推模式不同Kafka 采用的是拉模式PullConsumer 主动去 Broker 拉取数据这样可以根据自身处理能力控制消费速率。// Consumer 示例从 Topic 消费消息PropertiespropsnewProperties();props.put(bootstrap.servers,localhost:9092);props.put(group.id,order-consumer-group);props.put(key.deserializer,org.apache.kafka.common.serialization.StringDeserializer);props.put(value.deserializer,org.apache.kafka.common.serialization.StringDeserializer);KafkaConsumerString,StringconsumernewKafkaConsumer(props);consumer.subscribe(Collections.singletonList(order-topic));while(true){ConsumerRecordsString,Stringrecordsconsumer.poll(Duration.ofMillis(100));for(ConsumerRecordString,Stringrecord:records){System.out.printf(offset%d, key%s, value%s%n,record.offset(),record.key(),record.value());}}6. Consumer Group消费者组每个 Consumer 都属于一个 Consumer Group。Kafka 的消费模型有一条核心规则同一条消息只能被同一个 Consumer Group 中的一个 Consumer 消费但可以被多个不同的 Consumer Group 消费。这意味着同一个 Group 内的多个 Consumer 实现的是负载均衡消息分摊处理不同 Group 之间实现的是广播每个 Group 都能收到全量消息7. Replica副本Replica 是 Partition 的副本机制用来保障高可用。每个 Partition 可以配置多个 Replica其中一个是 Leader Replica负责所有的读写请求其余是 Follower Replica从 Leader 同步数据作为备份当 Leader 所在的 Broker 宕机时某个 Follower 会被选举为新的 Leader服务不中断。8. Controller控制器Controller 是 Kafka 集群中的一个特殊 Broker负责Partition 的 Leader 选举感知 Broker 的上下线执行各种 Failover 操作故障转移整个集群中只有一个 Controller它通过 Zookeeper 选举产生。如果当前 Controller 挂了其他 Broker 会重新竞选。9. ZookeeperKafka 通过 Zookeeper 来存储集群的元数据meta 信息包括Broker 注册信息Topic 和 Partition 的分配关系Consumer Group 的 offset旧版本Controller 的选举值得一提的是从 Kafka 2.8 开始引入了 KRaft 模式目标是去除对 Zookeeper 的依赖让 Kafka 自己管理元数据。这是 Kafka 架构演进的一个重要方向。二、Kafka 的优缺点优点特性说明高性能、高吞吐、低延迟生产和消费消息的速度都能达到每秒 10 万级依赖顺序写磁盘 零拷贝技术高可用所有消息持久化到磁盘支持多副本备份防止数据丢失高并发支持数千个客户端同时读写容错性允许集群中节点失败。若副本数量为 n则允许 n-1 个节点失败服务依然可用高扩展性集群支持热伸缩新增或移除 Broker 无须停机缺点没有完整的监控工具集Kafka 自身不提供开箱即用的监控 UI需要依赖第三方工具如 Kafka Eagle、Confluent Control Center、Prometheus Grafana 等不支持通配符主题选择Consumer 订阅 Topic 时不能像 MQTT 那样使用灵活的通配符匹配虽然支持正则订阅但功能相对有限三、Kafka 的应用场景Kafka 的应用场景非常丰富以下是最典型的几个场景一异步处理与服务解耦在微服务架构中服务之间的直接调用会产生强耦合。以电商下单为例用户下单后需要触发库存扣减、支付处理、短信通知、物流调度等多个下游操作。如果同步调用任何一个下游服务挂了整个下单流程就挂了。引入 Kafka 后订单服务只需要把下单事件丢到 Kafka各下游服务各自消费、各自处理互不影响。场景二日志收集与聚合这是 Kafka 最经典的应用场景之一。在分布式系统中日志散落在几十甚至上百台机器上直接写入存储系统如 Elasticsearch、HDFS会造成巨大压力。Kafka 作为中间缓冲层各服务将日志发送到 Kafka下游的日志分析系统ELK、Hadoop 等按自己的节奏消费处理。典型架构Filebeat / Log4j → Kafka → Elasticsearch / HDFS// 在 Java 应用中通过 Log4j2 将日志直接输出到 Kafka// log4j2.xml 中配置 KafkaAppender 后代码无需改动importorg.apache.logging.log4j.LogManager;importorg.apache.logging.log4j.Logger;publicclassOrderService{privatestaticfinalLoggerloggerLogManager.getLogger(OrderService.class);publicvoidcreateOrder(StringorderId){// 业务逻辑...logger.info(订单创建成功, orderId{},orderId);// 这条日志会通过 KafkaAppender 自动发送到 Kafka 的 log-topic}}场景三流量削峰秒杀、大促等场景下瞬时流量可能是平时的几十倍。数据库扛不住这种冲击但 Kafka 可以。请求先写入 Kafka 排队后端服务按自身处理能力匀速消费避免数据库被打崩。场景四实时数据流处理Kafka 不只是消息队列它还是一个流处理平台。配合 Kafka Streams、Apache Flink、Spark Streaming 等引擎可以对数据进行实时计算。典型场景实时风控用户每笔交易实时检测是否异常实时推荐根据用户实时行为更新推荐结果实时监控系统指标实时聚合告警// 使用 Kafka Streams 实时统计每分钟的订单数量PropertiespropsnewProperties();props.put(StreamsConfig.APPLICATION_ID_CONFIG,order-count-app);props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG,localhost:9092);StreamsBuilderbuildernewStreamsBuilder();KStreamString,Stringordersbuilder.stream(order-topic);// 按时间窗口统计订单数KTableWindowedString,LongorderCountsorders.groupBy((key,value)-all-orders).windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofMinutes(1))).count();orderCounts.toStream().foreach((windowedKey,count)-System.out.printf(窗口 [%s] 订单数: %d%n,windowedKey.window().startTime(),count));KafkaStreamsstreamsnewKafkaStreams(builder.build(),props);streams.start();场景五网站活动跟踪这也是 Kafka 最初在 LinkedIn 诞生时的核心用途。用户在网站上的每一次点击、浏览、搜索、购买行为都可以作为事件发送到 Kafka 的不同 Topic 中然后实时分析接入 Storm/Flink 做实时用户画像离线分析导入 Hadoop/MaxCompute 做用户行为分析报表场景六事件溯源与审计日志在金融、医疗等对数据完整性要求极高的领域Kafka 的日志持久化特性天然适合做事件溯源。每一次关键操作转账、审批、修改都作为不可变事件写入 Kafka任何时候都可以回溯完整的操作历史。场景七数据中转枢纽同一份数据往往需要被多个系统消费——搜索引擎要用、数据仓库要用、实时监控也要用。Kafka 的发布/订阅模型天然支持一对多消费充当数据管道的中转枢纽。