什么是Kafka
Kafka全称Apache Kafka,最初由Linkedin开发,并在2011年开源。是一个分布式流处理平台,主要用于构建实时数据管道和流处理程序。
主要特点
- 高吞吐量和低延迟:Kafka 能够处理大量的实时数据。
- 持久性和可靠性:Kafka 的数据存储在磁盘上,并且能够进行数据复制。
- 分布式架构:Kafka 是一个分布式系统,可以在多个服务器上运行,具有良好的水平扩展能力。
- 流处理能力:Kafka 提供了 Kafka Streams 和 Kafka Connect 两个组件,分别用于流处理和数据集成。
核心概念
- Producer(生产者):数据的生产者,将数据发送到 Kafka 特定的 Topic。
- Consumer(消费者):数据的消费者,负责从 Kafka 中的特定主题读取数据
- **Topic (主题):**主题是 Kafka 中用于分类和存储消息的逻辑逻辑命名空间。生产者可以将消息发送到一个或者多个主题,消费者也可以订阅一个或多个主题
- **Broker(代理)****:**Kafka 集群中的每个节点称为 Broker。每个 Broker 负责处理一个或多个分区的读写请求。
- Consumer Group(消费者组):消费者组由多个消费者实例组成。每个消费者组中的消费者实例共同消费主题中的消息,每个分区的消息只能被一个消费者实例消费。
工作流程
- 生产者发送消息:生产者将消息发送到 Kafka 集群中的一个或多个主题。
- 消息存储:Kafka 将消息存储在主题的分区中,并在磁盘上持久化。
- 消费者读取消息:消费者订阅一个或多个主题,从相应的分区中读取消息。
- 消息处理:消费者可以对读取到的消息进行处理,比如存储到数据库、进行实时分析等。
与其他 MQ 什么优劣
- kafka 设计的目标是用于高吞吐量和实时数据流处理,Mq一般都是基于AMQP协议,提供丰富的消息交换和路由机制,支持复杂的路由和可靠的消息传递
- kafka 支持数据重复,每个消费者组都可以移动消费点位重新消费互不影响。MQ 普遍不支持这种机制
- MQ 都有消息确认机制,这样可以保证了消息消费的可靠性,Kafka 不支持该特性
消费者概念
Kafka 消费者从属于消费者组
。一个群组中的消费者订阅的都是相同的主题,每个消费者接收主题一部分分区的消息
一个分区最多被一个消费者组
中的消费者消费,如果消费者组
中的消费者大于一个主题的分区数,那么就会有多余的消费者闲置,如图:
Rebalance(重平衡)当有消费者加入或者移出消费者组
的时候,就会触发重平衡
topic 的分区就会重新分配到不同的消费者去消费
C# 中怎么使用 Kafka
- 生产者发送消息:
-
using Confluent.Kafka; using System; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var config = new ProducerConfig { BootstrapServers = "localhost:9092" }; using var producer = new ProducerBuilder<Null, string>(config).Build(); try { var deliveryResult = await producer.ProduceAsync("test-topic", new Message<Null, string> { Value = "Hello Kafka!" }); Console.WriteLine($"Delivered '{deliveryResult.Value}' to '{deliveryResult.TopicPartitionOffset}'"); } catch (ProduceException<Null, string> e) { Console.WriteLine($"Delivery failed: {e.Error.Reason}"); } } }
生产者向队列发送消息需要提供一个 topic 名称和一个消息实体Message<null, string>
注意第一个参数是一个 key,如果 key 为 null,kafka会将消息轮询发送到分区;如果key有值,那么 kafka 会对 key hash到对应的分区。
-
消费者
using Confluent.Kafka; using System; using System.Threading; using System.Threading.Tasks;
class Program { static async Task Main(string[] args) { var config = new ConsumerConfig { GroupId = "test-group", BootstrapServers = "localhost:9092", AutoOffsetReset = AutoOffsetReset.Earliest };
using var consumer = new ConsumerBuilder<Ignore, string>(config).Build(); consumer.Subscribe("test-topic"); var cts = new CancellationTokenSource(); Console.CancelKeyPress += (_, e) => { e.Cancel = true; cts.Cancel(); }; try { while (true) { var cr = consumer.Consume(cts.Token); Console.WriteLine($"Consumed message '{cr.Value}' at: '{cr.TopicPartitionOffset}'."); } } catch (OperationCanceledException) { consumer.Close(); } }
}
每个消费者都要配置一个 groupId ,同一个消费者组的消费者一起消费一个 topic,一个分区只能被一个消费者消费
留个问题给同学们思考:多个消费者和分区,如何保证消息消费的顺序呢?