什么是 Kafka:
Kafka 是一款分布式消息发布和订阅系统,具有高性能、高吞吐量的特点。最初由 LinkedIn 公司开发,后贡献给 Apache 基金会成为顶级开源项目。
基本认识
设计目标
1.以时间复杂度为 O(1)的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间的访问性能。
2.高吞吐率,单机支持每秒 100k 条消息的传输。
3.支持 Kafka server 间的消息分区,及分布式消费,同时保证每个 partition 内的消息顺序传输。
4.同时支持离线数据处理和实时数据处理。
5.支持在线水平扩展(scale out)。
应用场景
行为跟踪:用于跟踪用户浏览页面、搜索及其他行为,通过发布-订阅模式实时记录到对应的 topic 中,再进行处理分析和监控。
日志收集系统:可作为日志聚合的代理,将应用程序的日志集中到 Kafka 上,然后分布导入到其他系统进行实时检索分析和离线统计数据备份等。
消息系统。
Kafka 名词解释
Broker:Kafka 集群中包含的服务器,一个或多个服务器构成 broker。Broker 端不维护数据的消费状态,直接使用磁盘进行存储,提升了性能,避免了内存复制和垃圾回收的性能损耗。
Producer:负责发布消息到 Kafka broker。
Consumer:负责从 broker 拉取(pull)数据并进行处理。
Topic:每条发布到 Kafka 集群的消息都有一个类别,即 topic。物理上不同 topic 的消息分开存储,逻辑上用户只需指定消费的 topic 即可生产或消费数据,而不必关心数据存于何处。
Partition:是物理上的概念,每个 topic 可包含一个或多个 partition,Kafka 分配的单位是 partition。
Consumer Group:每个 consumer 属于一个特定的 consumer group。可为每个 consumer 指定 group name,若不指定则属于默认的 group。每条消息只可以被 consumer group 组中的一个 consumer 消费,但可以指定多个 consumer group。
Kafka 分布式消息原理
topic 和 partition:
topic 可被视为一个逻辑上的队列。
partition 是 topic 的物理分区,每个 partition 是一个有序的队列,其中的消息都有一个连续的序列号(offset),用于唯一标识消息。
生产者消息分发:
Kafka 生产消息分发策略可自定义,默认情况下通常采用负载均衡机制随机选择分区,也可通过特定的分区函数选择分区。
消息默认的分发机制根据具体策略进行。
涉及到 metadata 类的相关操作。
消费者的消费原理:
kafaka 消息消费原理演示+测试:包括环境演示和测试等步骤,得出相应结论。
消费者分区分配策略有 rangeAssignor、roundRobinAssignor、stickyAssignor 等。
coordinator 在其中起到协调的作用。
coordinator:
确定方式有特定的算法和规则。
joinGroup 的过程包括 joinGroup、synchronizingGroupState 等步骤。
offset 的维护方式,包括 Kafka 怎么维护消费端的 offset、consumer 的 offset 分区算法、查看 offset 的命令等。
partition 的副本机制:
创建带副本机制的 topic。查看各个分区中对应的 leader。介绍副本的相关名词。阐述副本的协同工作方式。
isr(in-sync replicas,同步副本集合):明确加入 isr 集合的条件、lastCaughtUpTimeMs 标志的作用、kafka 副本管理器的工作原理,以及在所有 replica 不工作情况下的处理方式。
副本数据同步原理:
涉及数据处理过程、初始状态以及不同情况下的数据同步方式,还包括数据丢失原理和解决方案,以及 leader 副本的选举过程。
消息的存储:
消息的文件存储机制:将消息存储在文件中,以实现持久化。
logSegment 逻辑概念:包括 segment 文件命令规则、index 和 log 的对应关系,以及通过 offset 查找 message 的方式。
log 文件:分析 log 文件中的消息、日志清除策略(如删除或压缩)。
磁盘存储的性能问题:探讨如何优化磁盘存储以提高性能。
Kafka 消息的可靠性:确保消息在传输和存储过程中的可靠性,防止数据丢失等问题。
springboot集成kafka
1.导入spring-kafka依赖信息
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- kafkfa -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
2.在resources下创建文件application.yml
server:
port: 9991
spring:
application:
name: kafka-demo
kafka:
bootstrap-servers: 192.168.200.130:9092
producer:
retries: 10
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
consumer:
group-id: ${spring.application.name}-test
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
3.消息生产者
package com.heima.kafka.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
private KafkaTemplate<String,String> kafkaTemplate;
@GetMapping("/hello")
public String hello(){
kafkaTemplate.send("itcast-topic","代码星辰阁");
return "ok";
}
}
4.消息消费者
package com.heima.kafka.listener;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class HelloListener {
@KafkaListener(topics = "itcast-topic")
public void onMessage(String message){
if(!StringUtils.isEmpty(message)){
System.out.println(message);
}
}
}
传递消息为对象
目前springboot整合后的kafka,因为序列化器是StringSerializer,这个时候如果需要传递对象可以有两种方式
方式一:可以自定义序列化器,对象类型众多,这种方式通用性不强,本章节不介绍
方式二:可以把要传递的对象进行转json字符串,接收消息后再转为对象即可,本项目采用这种方式
发送消息
@GetMapping("/hello")
public String hello(){
User user = new User();
user.setUsername("xiaowang");
user.setAge(18);
kafkaTemplate.send("user-topic", JSON.toJSONString(user));
return "ok";
}
接收消息
package com.heima.kafka.listener;
import com.alibaba.fastjson.JSON;
import com.heima.kafka.pojo.User;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class HelloListener {
@KafkaListener(topics = "user-topic")
public void onMessage(String message){
if(!StringUtils.isEmpty(message)){
User user = JSON.parseObject(message, User.class);
System.out.println(user);
}
}
}
END
文字丨代码星辰阁
图片丨代码星辰阁