文章目录
前言
Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。该项目的目标是为处理实时数据提供一个统一、高吞吐、低延迟的平台。其持久化层本质上是一个“按照分布式事务日志架构的大规模发布/订阅消息队列”,这使它作为企业级基础设施来处理流式数据非常有价值。
Kafka 的核心特性可以总结为以下几个方面:
-
发布订阅模型:
- Kafka 使用类似于消息队列的发布订阅模型,但更侧重于消息持久化以及支持多消费者模型。
- 生产者(Producer)将消息发送到主题(Topic),消费者(Consumer)则订阅这些主题来消费消息。
- 消费者可以是多个消费者组成的消费者组(Consumer Group),这样可以实现消息的并行处理。
-
可扩展性:
- Kafka 能够水平扩展,通过增加更多的服务器节点可以提升系统的吞吐量。
- Kafka 可以部署在分布式集群中,具有很强的容错能力。
-
持久性和可靠性:
- Kafka 将消息存储在磁盘上,并允许复制到多个服务器上以防止数据丢失。
- Kafka 保证消息的顺序性,在一个分区内的消息会按照它们被发送的顺序存储和读取。
-
高性能:
- Kafka 设计为支持高吞吐量,即使在非常大的数据集上也能保持低延迟。
- Kafka 利用零拷贝技术来提高性能,这意味着它可以在不复制数据的情况下直接从磁盘读取数据到网络栈。
-
存储:
- Kafka 的数据存储是基于日志文件的,这意味着它可以有效地存储大量数据。
- Kafka 支持数据保留策略,可以根据时间和大小来决定何时删除旧数据。
-
流处理:
- Kafka Streams API 允许开发者创建复杂的流处理应用程序,如实时聚合、过滤和转换数据等操作。
- Kafka 还与其他流处理框架(如 Apache Flink 和 Apache Spark Streaming)集成良好。
Apache Kafka 是一个非常强大的流处理平台,它被广泛应用于多种不同的场景中。以下是 Kafka 的一些典型应用场景:
1. 日志处理与分析
- 日志收集:Kafka 可以收集来自不同服务的日志数据,如 Web 服务器、应用服务器、数据库服务器等。
- 日志聚合:将收集的日志数据聚合起来,以便进一步分析。
- 日志分析:通过集成工具(如 Apache Flink, Hadoop, Elasticsearch 等)进行实时或批量分析。
2. 消息队列
- 异步通信:Kafka 可以作为消息中间件,实现服务间的异步通信,降低服务耦合度。
- 消息缓冲:在消息生产者和消费者之间提供缓冲,帮助平衡负载。
- 服务解耦:通过消息队列实现服务之间的解耦。
3. 实时数据流处理
- 实时分析:处理实时数据流,执行复杂的事件处理、转换和分析操作。
- 流式数据处理:构建实时数据处理流水线,例如实时计算、警报触发等。
4. 系统监控与报警
- 指标收集:收集各种监控指标,并实时处理这些数据。
- 异常检测:基于实时数据流检测异常行为,并及时发出警报。
5. 流量削峰
- 负载均衡:通过设置消息队列的最大容量来控制客户端流量,避免后端服务过载。
6. 高可用性
- 多副本冗余:Kafka 的多副本机制确保了数据的高可用性。
- 容错性:即使部分节点发生故障,Kafka 仍然能够保证数据的可靠性和持续的服务。
7. 分布式任务调度
- 任务管理:通过 Kafka 发布任务,多个消费者可以并发地处理这些任务。
8. 物联网 (IoT)
- 传感器数据处理:处理来自 IoT 设备的大量数据流。
一、Kafka 的基本架构?
下面是 Kafka 架构的主要组成部分:
1. Producer(生产者)
- 生产者是向 Kafka 发布消息的应用程序或服务。
- 生产者可以选择将消息发送到特定的
topic
和partition
。 - 生产者还负责选择消息的
key
,这会影响消息如何被分发到分区。
2. Broker(代理/服务器)
- Kafka 集群由一个或多个服务器组成,这些服务器称为 Broker。
- Broker 负责接收来自生产者的消息并将它们存储在磁盘上。
- 每个 Broker 可以托管一个或多个
topic
的分区。 - Broker 也负责将消息发送给消费者。
3. Consumer(消费者)
- 消费者是从 Kafka 中读取消息的应用程序或服务。
- 消费者可以订阅一个或多个
topic
,并且只能从自己订阅的topic
中读取数据。 - 消费者可以从特定的时间点开始读取历史数据,也可以从最新的消息开始读取。
4. Consumer Group(消费者组)
- 一个
consumer group
是一组具有相同group id
的消费者。 - 每个
topic
的分区只会被分配给同一个consumer group
中的一个消费者。 - 这种机制允许消息被并行处理,并且提供了容错性,因为如果一个消费者失败,它的分区会被重新分配给同一个组内的其他消费者。
5. Topic(主题)
Topic
是一种逻辑类别,用于组织和发布消息。- 一个
topic
可以包含多个partition
。 - 每个
topic
都有一个预定义的配置,比如分区数量、复制因子等。
6. Partition(分区)
Partition
是topic
的物理分割,每个partition
是一个有序的不可变消息序列。- 分区可以分布在多个 Broker 上,这使得 Kafka 能够水平扩展。
- 每个
partition
都有一个主broker
(leader)以及可能的一些副本broker
(follower)。
7. Replication(复制)
- 为了确保高可用性和容错性,每个
partition
都可以有多个副本。 - 除了一个主副本(leader)之外,还可以有从副本(follower),这些副本会在不同的 Broker 上存储同一份数据。
- 如果主副本出现故障,其中一个从副本可以被提升为主副本。
8. ZooKeeper
- Kafka 使用 ZooKeeper 来管理集群的元数据,包括:
broker
的注册和发现。topic
的配置。consumer group
的状态。- 分区的领导者选举。
二、代码测试
1.引入依赖
<!-- Spring Kafka Starter -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
2.启动
在Linux下安装、配置、启动
在IDEA中配置
spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
3.创建生产者
@RestController
public class ProducerController {
private static final Logger log = LoggerFactory.getLogger(ProducerController.class);
private static final String TOPIC = "admin-messages";
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@PostMapping("/sendMessage")
public String sendMessage(@RequestBody FrontEvent frontEvent) {
String json = JSON.toJSONString(frontEvent);
kafkaTemplate.send(TOPIC, json);
log.info("Send message=========={}",json);
return "send success!";
}
}
4.创建消费者
@Component
public class Consumer{
private static final Logger log = LoggerFactory.getLogger(Consumer.class);
@KafkaListener(topics = "admin-messages",groupId = "myGroupId")
public void receiveAdminMessage(String message) {
try {
FrontEvent frontEvent = JSON.parseObject(message, FrontEvent.class);
log.info("Received message=========={}", frontEvent.toString());
// 保存到数据库
//frontEventRepository.save(frontEvent);
} catch (Exception e) {
// 如果发生异常,则需要进行失败重试,需手动设置重试次数,死信队列
// 手动ack ack.acknowledge();
log.error("Failed to process the message: {}", message, e);
}
}
}