对kafka提供的机制做一次全局视野的解析(大概)

我们要把握kafka可以从几个角度来把握

1.如何搭建kafka环境,搭建好了如何配置,springboot如何连接kafka的机构

2.搭建好了kafka(broker)相关的机制

2.1 broker的性质,## 标题,lerder和follower

2.2对于topic这一层。需要了解的概念,分区,副本

2.3 springboot创建topic,一般要制定分区和副本

2.4min.insync.replicas(最小同步副本数):这是搭配生产者 acks=all 使用的服务器端铁闸。它规定"如果副本存活数少于这个值,Broker 直接拒绝写入"。这防止了集群只剩 Leader 自己时(比如只剩一台机器),生产者还傻乎乎地写数据(虽然 acks=all,但只有 Leader 自己确认也算数),结果这台机器一挂,数据全丢。

3.springboot如何做一个生产者。kafka提供了哪些机制给生产者

生产者创建topic需要了解的信息量

topic落数据的机制

生产这个发送消费的方式:同步发送,异步发送

生产者发送消息的消息的"三大件"

生产者发送消息需要多少副本确认"收到"后,才算真正发送成功。

生产者发送消息的幂等性

生产者发送消息的事务性

4.springboot如何做一个生产者。kafka提供了哪些机制给消费者

消费者拉取kafka的topic的方式

Kafka 消费者的工作流程

消费者组,消费topic分区的方式

offsets自动,手动记录机制

消费者组,消费topic分区的方式:

场景一:横向扩容(多个SpringBoot,相同的 group.id)------ 负载均衡模式

做法:你把同一个 SpringBoot 代码,部署在 3台服务器 上,application.yml 里的 group.id 完全一样(比如都是 order-process-group)。

效果:这3个实例属于同一个消费者组。Kafka 会把 Topic 里的分区平均分配给这3台机器。比如 Topic 有 3 个分区,就一台机器消费一个分区。

目的:为了扛住高并发。3台机器并行消费,吞吐量是单机的3倍。

你的代码改动:完全不用改。你只需要在部署时,给每台机器指定同样的 group.id 即可。

场景二:业务隔离(多个SpringBoot,不同的 group.id)------ 广播/独立模式

做法:你有两个微服务,订单服务 和 积分服务。它们都订阅了同一个 order-topic,但配置完全不同:

订单服务的 YAML:group-id: group-order-service

积分服务的 YAML:group-id: group-point-service

效果:这是两个完全独立的消费者组。Kafka 会把 order-topic 里的每一条消息,同时推送给 group-order-service 和 group-point-service。两个服务各拿一份全量数据,互不干扰。

目的:为了解耦微服务。订单系统管订单状态,积分系统管加积分,大家各干各的。

你的代码改动:两个独立的 SpringBoot 项目,各自配置自己的 group.id

场景三:单机多线程(一个SpringBoot,多个 @KafkaListener)------ 并发消费

做法:你只有一个 SpringBoot 服务,但为了提高处理速度,你想在一个 JVM 里开 3个线程 同时消费。

效果:Spring 允许你在 @KafkaListener 注解上加一个 concurrency 参数,比如 @KafkaListener(topic="my-topic", concurrency="3")。

底层机制:Spring 会在后台创建 3 个消费者线程,它们共享同一个 group.id,Kafka 会把分区分配这 3 个线程。

注意:这种模式下,并发数(concurrency)不能超过 Topic 的分区数。如果 Topic 只有 2 个分区,你开 concurrency=3,第 3 个线程会一直空闲。

这份博客提纲的骨架已经搭建得很扎实了。下面我为你填充了各章节的核心知识点、关键配置和原理剖析,你可以根据这些内容来丰满你的博客文章。


1. 如何搭建Kafka环境,搭建好了如何配置,Spring Boot如何连接Kafka

1.1 环境搭建

Kafka的运行依赖ZooKeeper(新版本正在逐步去依赖,但目前依然广泛使用)。

  • 使用Docker快速搭建(推荐)
    1. 启动ZooKeeper:

      bash 复制代码
      docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
    2. 启动Kafka:

      bash 复制代码
      docker run -d --name kafka \
        -p 9092:9092 \
        -e KAFKA_BROKER_ID=1 \
        -e KAFKA_ZOOKEEPER_CONNECT=192.168.xx.xx:2181 \
        -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://192.168.xx.xx:9092 \
        -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 \
        wurstmeister/kafka:2.12-2.3.1

      注意KAFKA_ADVERTISED_LISTENERS 需要配置为你的宿主机IP,否则Spring Boot无法连接。

1.2 Spring Boot整合配置
  • 引入依赖 :在 pom.xml 中添加 spring-boot-starter-kafka

    xml 复制代码
    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
    </dependency>
  • YML配置 :在 application.yml 中配置最基本的连接信息。

    yaml 复制代码
    spring:
      kafka:
        bootstrap-servers: 192.168.xx.xx:9092
        producer:
          key-serializer: org.apache.kafka.common.serialization.StringSerializer
          value-serializer: org.apache.kafka.common.serialization.StringSerializer
        consumer:
          group-id: my-group
          key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
          value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

2. Kafka Broker 相关机制

2.1 Broker的性质:Leader 和 Follower
  • Leader :每个分区的唯一读写入口。所有的生产者和消费者请求都只会与Leader副本交互。
  • Follower :作为冗余备份 ,不对外提供服务。它们会实时从Leader拉取数据进行同步,以保证与Leader的数据一致性。
  • 故障转移:当Leader所在的Broker宕机时,Kafka会从该分区的Follower中选举一个新的Leader,保证服务的高可用。
2.2 Topic层的概念:分区与副本
  • 分区 (Partition) :Topic的物理分片 。一个Topic可以包含多个分区,分布在不同的Broker上,是实现水平扩展高吞吐量的基础。
  • 副本 (Replica) :分区的冗余备份 ,用于保证高可用性数据持久性
  • ISR (In-Sync Replicas)同步副本集合,是与Leader保持同步的所有副本的集合(包含Leader自己)。只有ISR中的副本才有资格被选举为新的Leader。
2.3 Spring Boot 创建 Topic

在Spring Boot中,我们可以通过 NewTopic Bean来定义Topic的分区数和副本数。

java 复制代码
@Configuration
public class KafkaTopicConfig {
    @Bean
    public NewTopic myTopic() {
        // 指定Topic名称,分区数为3,副本因子为1(单机环境)
        return TopicBuilder.name("my-topic")
                .partitions(3)
                .replicas(1)
                .build();
    }
}
2.4 min.insync.replicas:数据安全的最后一道防线
  • min.insync.replicas 是Broker端(Topic级别)的配置,它规定了当生产者使用 acks=all 时,至少需要多少个ISR副本确认写入,才算成功
  • 典型配置 :如果副本因子为3,建议将 min.insync.replicas 设置为2。
  • 作用:防止当集群中只剩Leader一个副本存活时(极端情况),生产者仍写入数据并返回成功,造成数据丢失。

3. Spring Boot 生产者与 Kafka 提供的机制

3.1 生产者创建Topic需要了解的信息量

生产者不负责创建Topic。Topic的创建通常由运维人员手动创建 ,或通过Spring Boot的NewTopic Bean在应用启动时创建。

3.2 Topic落数据的机制

数据以追加的方式写入分区日志(Log),消息在分区内是严格有序的。

3.3 发送方式:同步与异步
  • 同步发送 :调用 send() 方法后,等待 Future.get() 返回结果,能直接感知发送成功或失败,但性能较低。
  • 异步发送 :调用 send() 时传入一个回调(Callback) ,在回调的 onCompletion() 方法中处理成功或失败逻辑。这是生产环境推荐的方式。
3.4 消息的"三大件"

Kafka消息由三部分组成:

  • Topic:消息发往的主题。
  • Key:用于决定消息进入哪个分区(如果为null,则使用轮询策略)。
  • Value:消息的实际内容。
3.5 生产者ACK机制:多少副本确认才算成功

生产者通过 acks 参数控制消息的可靠性,有三种级别:

  • acks=0最高吞吐,最低可靠。生产者发完即忘,不等待任何确认,数据可能丢失。
  • acks=1默认值,中等可靠。Leader将消息写入本地日志后即返回确认。如果Leader在Follower同步前宕机,数据可能丢失。
  • acks=all (或 -1)最高可靠,最低吞吐 。Leader会等待ISR中的所有副本 都确认写入后,才返回成功。配合 min.insync.replicas 可保证数据绝对不丢。
3.6 幂等性 (Idempotence)
  • 解决问题 :解决生产者重试 时导致的消息重复问题。
  • 原理 :开启幂等性(enable.idempotence=true)后,Broker会根据生产者ID(PID)和序列号为每个消息去重。
  • 限制 :只能在单分区、单会话内保证不重复。
3.7 事务性 (Transaction)
  • 解决问题 :解决跨分区、跨会话的消息原子性问题。
  • 场景:比如一个原子操作需要同时向多个Topic发送消息,要么全部成功,要么全部失败。
  • 实现 :通过Kafka的事务API,结合 transactional.id 配置来实现。

4. Spring Boot 消费者与 Kafka 提供的机制

4.1 消费者拉取方式

Kafka消费者采用主动拉取(Pull) 的模式。消费者不断向Broker发起拉取请求,获取新消息。

4.2 Kafka 消费者的工作流程
  1. 初始化:消费者配置并订阅Topic。
  2. 发现协调者 :向Broker请求找到组协调者(Group Coordinator)
  3. 加入消费者组 :向协调者发送 JoinGroup 请求,参与分区分配(Rebalance)。
  4. 分配分区:协调者根据分配策略(如Range、RoundRobin)为消费者分配分区。
  5. 拉取消息:消费者开始从分配到的分区拉取并消费消息。
  6. 提交位移:消费者消费后,提交Offset(位移),记录消费进度。
4.3 消费者组与分区消费方式
  • 消费者组 (Consumer Group):由一个或多个消费者实例组成。
  • 分区分配 :一个分区只能 被同一个消费者组内的一个消费者消费。
  • 并行度 :消费者组内的消费者数量不能超过Topic的分区数,否则多余的消费者将空闲。
4.4 Offset的自动与手动提交机制

Offset是消费者在分区内的消费位置标记,存储在Broker的 __consumer_offsets 主题中。

  • 自动提交 (默认)

    • enable.auto.commit=true
    • 每隔 auto.commit.interval.ms(默认5秒)自动提交上一次拉取的最大Offset。
    • 风险 :可能造成消息重复消费消息丢失
  • 手动提交 (推荐生产环境)

    • enable.auto.commit=false
    • 使用 commitSync()(同步)或 commitAsync()(异步)方法手动提交。
    • 最佳实践先完成业务逻辑,再提交Offset。确保只有消息被成功处理后,位移才会提交,从而避免消息丢失。