
大家好,我是月夜枫。
什么是Kafka?
Kafka 是一个分布式事件流平台,主要用于高吞吐量的实时数据传输与处理。
核心能做什么?
- 消息传递:支持发布和订阅数据流,类似消息队列,实现系统间解耦与通信 。
- 数据存储:将数据流持久化存储在分布式集群中,支持长期保留与回溯 。
- 流式处理:提供流处理 API,可对实时数据流进行转换、聚合和分析。
常见应用场景有哪些?
- 日志收集:统一采集各服务日志,供 Hadoop、Elasticsearch 等系统分析 。
- 实时监控:追踪用户行为、运营指标,支持实时风控与推荐系统 。
- 数据管道:在数据库、数据仓库等不同系统间可靠地传输数据。
有什么特点?
- 高性能:每秒可处理数百万级消息,延迟低至毫秒级 。
- 高可靠:采用多副本机制和持久化存储,保障数据不丢失 。
- 易扩展:支持集群水平扩展,新版架构已逐步取代 ZooKeeper 依赖
在分布式系统的世界里,有一个名字如雷贯耳——Kafka!它就像一条超级高速公路,承载着海量数据在各个服务之间飞速穿梭。从电商秒杀到实时监控,从日志收集到大数据分析,Kafka 无处不在。
今天就带大家深入 Kafka 的世界,从原理到实战,手把手教你在 SpringBoot 中玩转这个高性能消息队列神器!
一、Kafka 核心概念图解
在开始代码实战之前,我们先来理解一下 Kafka 的核心架构:

核心组件说明:
|
组件 |
作用 |
关键特性 |
| Producer |
消息生产者 |
支持批量发送、异步发送 |
| Consumer |
消息消费者 |
支持分组消费、并发消费 |
| Broker |
消息代理节点 |
存储消息、处理请求 |
| Topic |
消息主题 |
按主题分类存储消息 |
| Partition |
分区 |
实现并行处理和负载均衡 |
| Offset |
偏移量 |
记录消费位置 |
二、为什么 Kafka 这么快?
很多小伙伴可能会好奇,Kafka 为什么能达到每秒几十万条消息的吞吐量?
核心优化策略:
1. 顺序写入磁盘 - 避免随机 IO,磁盘顺序写入速度接近内存。
2. 零拷贝技术 - 数据直接从内核缓冲区发送到网络,无需用户态拷贝。
3. 批量压缩 - 批量发送消息并压缩,减少网络传输量。
4. 分区并行 - 多个分区同时处理,提高整体吞吐量。
三、实战:SpringBoot 整合 Kafka
3.1 环境准备
首先确保你的 Kafka 环境已经就绪:
# 1. 启动 ZooKeeper(Kafka 依赖)
bin/zookeeper-server-start.sh config/zookeeper.properties
# 2. 启动 Kafka 服务
bin/kafka-server-start.sh config/server.properties
# 3. 创建测试主题(3个分区,1个副本)
bin/kafka-topics.sh --create \
--topic order-topic \
--bootstrap-server localhost:9092 \
--partitions 3 \
--replication-factor 1
这里解释一下,Kafka < 2.8:必须依赖 ZooKeeper,否则是无法启动或运行。
Kafka 2.8 ~ 3.x:可选模式。既支持传统 ZooKeeper 模式,也支持实验性/生产就绪的KRaft 模式(无 ZooKeeper)。
Kafka 3.3.1 后 KRaft 标记为生产就绪 。
Kafka ≥ 4.0:完全移除 ZooKeeper 代码路径,仅支持 KRaft 模式,无需也无法连接 ZooKeeper 。
因为版本问题,按2.8版本作为演示基础。
3.2 项目配置
添加 Maven 依赖:
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
application.yml 配置详解:
spring:
kafka:
bootstrap-servers: localhost:9092
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
acks: all # 等待所有副本确认
retries: 3 # 重试次数
batch-size: 16384 # 批量大小(16KB)
linger-ms: 5 # 等待5ms批量发送
buffer-memory: 33554432 # 缓冲区大小(32MB)
consumer:
group-id: order-consumer-group
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
auto-offset-reset: earliest # 从最早开始消费
enable-auto-commit: false # 手动提交偏移量
max-poll-records: 100 # 每次拉取100条
3.3 消息实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderMessage {
private String orderId;
private String userId;
private BigDecimal amount;
private LocalDateTime createTime;
}
3.4 生产者实现
@Component
public class OrderProducer {
private static final String TOPIC = "order-topic";
private final KafkaTemplate<String, OrderMessage> kafkaTemplate;
@Autowired
public OrderProducer(KafkaTemplate<String, OrderMessage> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
/**
* 发送订单消息(异步)
*/
public void sendOrderMessage(OrderMessage message) {
ListenableFuture<SendResult<String, OrderMessage>> future =
kafkaTemplate.send(TOPIC, message.getOrderId(), message);
future.addCallback(
result -> {
RecordMetadata metadata = result.getRecordMetadata();
log.info("消息发送成功 | Topic: {}, Partition: {}, Offset: {}",
metadata.topic(), metadata.partition(), metadata.offset());
},
exception -> {
log.error("消息发送失败 | OrderId: {}, Error: {}",
message.getOrderId(), exception.getMessage());
}
);
}
}
3.5 消费者实现
@Component
public class OrderConsumer {
@KafkaListener(
topics = "order-topic",
groupId = "order-consumer-group",
concurrency = "3" // 3个并发消费者
)
public void consumeOrderMessage(
@Payload OrderMessage message,
@Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
@Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition,
@Header(KafkaHeaders.OFFSET) long offset,
Acknowledgment acknowledgment
) {
try {
// 业务处理:扣减库存、生成发货单等
processOrder(message);
// 手动提交偏移量
acknowledgment.acknowledge();
log.info("消费成功 | OrderId: {}, Topic: {}, Partition: {}, Offset: {}",
message.getOrderId(), topic, partition, offset);
} catch (Exception e) {
log.error("消费失败 | OrderId: {}, Error: {}",
message.getOrderId(), e.getMessage());
// 可以根据业务需求决定是否重试或死信队列
}
}
private void processOrder(OrderMessage message) {
// 订单处理逻辑
log.info("处理订单: {}", message.getOrderId());
}
}
3.6 测试接口
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderProducer orderProducer;
@Autowired
public OrderController(OrderProducer orderProducer) {
this.orderProducer = orderProducer;
}
@PostMapping
public ResponseEntity<String> createOrder(@RequestBody OrderDTO orderDTO) {
OrderMessage message = OrderMessage.builder()
.orderId(UUID.randomUUID().toString())
.userId(orderDTO.getUserId())
.amount(orderDTO.getAmount())
.createTime(LocalDateTime.now())
.build();
orderProducer.sendOrderMessage(message);
return ResponseEntity.ok("订单已创建,消息已发送");
}
}
四、高级特性实战
4.1 事务消息
@Configuration
public class KafkaTransactionConfig {
@Bean
public KafkaTransactionManager<String, OrderMessage> kafkaTransactionManager(
ProducerFactory<String, OrderMessage> producerFactory) {
return new KafkaTransactionManager<>(producerFactory);
}
}
// 在生产者中使用事务
@Transactional
public void sendOrderMessageTransactional(OrderMessage message) {
// 先保存数据库
orderRepository.save(message);
// 再发送消息
kafkaTemplate.send(TOPIC, message);
}
4.2 死信队列配置
@Bean
public DeadLetterPublishingRecoverer deadLetterPublishingRecoverer(
KafkaTemplate<String, OrderMessage> kafkaTemplate) {
return new DeadLetterPublishingRecoverer(kafkaTemplate);
}
@Bean
public ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory(
ConcurrentKafkaListenerContainerFactoryConfigurer configurer,
ConsumerFactory<Object, Object> kafkaConsumerFactory,
DeadLetterPublishingRecoverer deadLetterPublishingRecoverer) {
ConcurrentKafkaListenerContainerFactory<Object, Object> factory =
new ConcurrentKafkaListenerContainerFactory<>();
configurer.configure(factory, kafkaConsumerFactory);
// 设置异常恢复器(死信队列)
factory.setErrorHandler(new SeekToCurrentErrorHandler(deadLetterPublishingRecoverer, 3));
return factory;
}
4.3 消息过滤
@Bean
public ConcurrentKafkaListenerContainerFactory<String, OrderMessage> filterContainerFactory(
ConsumerFactory<String, OrderMessage> consumerFactory) {
ConcurrentKafkaListenerContainerFactory<String, OrderMessage> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory);
// 过滤掉金额小于100的订单
factory.setRecordFilterStrategy(
record -> record.value().getAmount().compareTo(BigDecimal.valueOf(100)) < 0
);
return factory;
}
// 使用过滤工厂
@KafkaListener(
topics = "order-topic",
groupId = "filter-group",
containerFactory = "filterContainerFactory"
)
public void consumeFilteredOrder(OrderMessage message) {
log.info("过滤后消费: {}", message);
}
五、性能监控与调优
5.1 监控指标
|
指标 |
说明 |
监控方式 |
| 消息延迟 |
从生产到消费的时间 |
Kafka Consumer Metrics |
| 消费速率 |
每秒消费消息数 |
Kafka Consumer Metrics |
| 分区偏移量 |
各分区消费进度 |
Kafka AdminClient |
| Broker 健康 |
一是集群内部自动检测节点存活的机制; 二是运维层面监控 Broker 运行状态,核心作用是保障集群 高可用、及时发现故障并自动容灾。 |
Kafka Health Check |
5.2 调优建议
# 生产环境推荐配置
spring:
kafka:
producer:
compression-type: snappy # 使用 snappy 压缩
batch-size: 32768 # 增大批次
linger-ms: 100 # 等待100ms
consumer:
fetch-min-bytes: 10240 # 最小拉取10KB
fetch-max-wait-ms: 500 # 最多等待500ms
结尾
通过这篇文章,我们一起学习了:
1. ✅ Kafka 的核心架构与原理
2. ✅ SpringBoot 整合 Kafka 的完整流程
3. ✅ 生产者、消费者的最佳实践
4. ✅ 事务消息、死信队列等高级特性
5. ✅ 性能调优与监控建议
学习本就是一个长期积累的过程,没有捷径,唯有坚持。希望能够真正帮到你,学以致用,不断提升,在自己的领域里越走越远。
互动时刻:你在项目遇到过什么有趣的问题?欢迎在留言区分享你的经验!👇如果这篇文章对你有帮助,别忘了点赞、在看、转发三连支持!💪

3857

被折叠的 条评论
为什么被折叠?



