我们要把握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快速搭建(推荐) :
-
启动ZooKeeper:
bashdocker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14 -
启动Kafka:
bashdocker 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中配置最基本的连接信息。yamlspring: 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 消费者的工作流程
- 初始化:消费者配置并订阅Topic。
- 发现协调者 :向Broker请求找到组协调者(Group Coordinator)。
- 加入消费者组 :向协调者发送
JoinGroup请求,参与分区分配(Rebalance)。 - 分配分区:协调者根据分配策略(如Range、RoundRobin)为消费者分配分区。
- 拉取消息:消费者开始从分配到的分区拉取并消费消息。
- 提交位移:消费者消费后,提交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。确保只有消息被成功处理后,位移才会提交,从而避免消息丢失。