KafKa介绍(分布式架构)

介绍

Kafka是一个分布式的、可分区的、可复制的消息系统。它提供了普通消息系统的功能,但具有自己独特的设计。这个独特的设计是什么样的呢?

首先让我们看几个基本的消息系统术语:

  • Kafka将消息以topic为单位进行归纳。

  • 将向Kafka topic发布消息的程序成为producers.

  • 将预订topics并消费消息的程序成为consumer.

  • Kafka以集群的方式运行,可以由一个或多个服务组成,每个服务叫做一个broker.

producers通过网络将消息发送到Kafka集群,集群向消费者提供消息,如下图所示:

客户端和服务端通过TCP协议通信。Kafka提供了Java客户端,并且对多种语言都提供了支持。

 Topics 和Logs

先来看一下Kafka提供的一个抽象概念:topic.

一个topic是对一组消息的归纳。对每个topic,Kafka 对它的日志进行了分区,如下图所示:

每个分区都由一系列有序的、不可变的消息组成,这些消息被连续的追加到分区中。分区中的每个消息都有一个连续的序列号叫做offset,用来在分区中唯一的标识这个消息。

在一个可配置的时间段内,Kafka集群保留所有发布的消息,不管这些消息有没有被消费。比如,如果消息的保存策略被设置为2天,那么在一个消 息被发布的两天时间内,它都是可以被消费的。之后它将被丢弃以释放空间。Kafka的性能是和数据量无关的常量级的,所以保留太多的数据并不是问题。

实际上每个consumer唯一需要维护的数据是消息在日志中的位置,也就是offset.这个offset有consumer来维护:一般情 况下随着consumer不断的读取消息,这offset的值不断增加,但其实consumer可以以任意的顺序读取消息,比如它可以将offset设置 成为一个旧的值来重读之前的消息。

以上特点的结合,使Kafka consumers非常的轻量级:它们可以在不对集群和其他consumer造成影响的情况下读取消息。你可以使用命令行来"tail"消息而不会对其他正在消费消息的consumer造成影响。

将日志分区可以达到以下目的:首先这使得每个日志的数量不会太大,可以在单个服务上保存。另外每个分区可以单独发布和消费,为并发操作topic提供了一种可能。

分布式

每个分区在Kafka集群的若干服务中都有副本,这样这些持有副本的服务可以共同处理数据和请求,副本数量是可以配置的。副本使Kafka具备了容错能力。

每个分区都由一个服务器作为“leader”,零或若干服务器作为“followers”,leader负责处理消息的读和 写,followers则去复制leader.如果leader down了,followers中的一台则会自动成为leader。集群中的每个服务都会同时扮演两个角色:作为它所持有的一部分分区的leader,同 时作为其他分区的followers,这样集群就会据有较好的负载均衡。

Producers
Producer将消息发布到它指定的topic中,并负责决定发布到哪个分区。通常简单的由负载均衡机制随机选择分区,但也可以通过特定的分区函数选择分区。使用的更多的是第二种。
Consumers
发布消息通常有两种模式:队列模式和发布-订阅模式。队列模式中,consumers可以同时从服务端读取消息,每个消息只被其中一个consumer读到;发布-订阅模式中消息被广播到所有的consumer中。
Consumers可以加入一个consumer 组,共同竞争一个topic,topic中的消息将被分发到组中的一个成员中。同一组中的consumer可以在不同的程序中,也可以在不同的机器上。如果所有的consumer都在一个组中,这就成为了传统的队列模式,在各consumer中实现负载均衡。
如果所有的consumer都不在不同的组中,这就成为了发布-订阅模式,所有的消息都被分发到所有的consumer中。

更常见的是,每个topic都有若干数量的consumer组,每个组都是一个逻辑上的“订阅者”,为了容错和更好的稳定性,每个组由若干consumer组成。这其实就是一个发布-订阅模式,只不过订阅者是个组而不是单个consumer。

由两个机器组成的集群拥有4个分区 (P0-P3) 2个consumer组. A组有两个consumerB组有4个

相比传统的消息系统,Kafka可以很好的保证有序性。

传统的队列在服务器上保存有序的消息,如果多个consumers同时从这个服务器消费消息,服务器就会以消息存储的顺序向consumer分 发消息。虽然服务器按顺序发布消息,但是消息是被异步的分发到各consumer上,所以当消息到达时可能已经失去了原来的顺序,这意味着并发消费将导致 顺序错乱。为了避免故障,这样的消息系统通常使用“专用consumer”的概念,其实就是只允许一个消费者消费消息,当然这就意味着失去了并发性。

在这方面Kafka做的更好,通过分区的概念,Kafka可以在多个consumer组并发的情况下提供较好的有序性和负载均衡。将每个分区分 只分发给一个consumer组,这样一个分区就只被这个组的一个consumer消费,就可以顺序的消费这个分区的消息。因为有多个分区,依然可以在多 个consumer组之间进行负载均衡。注意consumer组的数量不能多于分区的数量,也就是有多少分区就允许多少并发消费。

Kafka只能保证一个分区之内消息的有序性,在不同的分区之间是不可以的,这已经可以满足大部分应用的需求。如果需要topic中所有消息的有序性,那就只能让这个topic只有一个分区,当然也就只有一个consumer组消费它。

愿意了解框架技术或者源码的朋友直接加求求(企鹅):2042849237
更多详细源码参考来源:http://minglisoft.cn/technology

转载于:https://www.cnblogs.com/wodeyueliang/p/6877374.html

<think>我们被要求介绍Kafka分布式架构。根据引用[1][2][3][5]提供的资料,Kafka分布式架构设计是其核心优势之一,它通过分区、副本、消费者组等机制实现了高吞吐量、低延迟、高可用性和容错性。下面我们将系统性地介绍Kafka分布式架构。 ### Kafka分布式架构介绍 Kafka分布式架构主要由以下组件构成: 1. **Broker**:Kafka集群中的每个服务器节点称为Broker,负责消息的存储和转发。 2. **Topic**:消息的逻辑分类,一个Topic可以分为多个Partition(分区)。 3. **Partition**:每个Topic被分成多个Partition,每个Partition是一个有序、不可变的消息序列。 4. **Replica**:每个Partition有多个副本,包括一个Leader副本和多个Follower副本,通过副本机制提供高可用性。 5. **Producer**:生产者,向Topic发布消息。 6. **Consumer**:消费者,从Topic订阅并消费消息。 7. **Consumer Group**:消费者组,由多个消费者实例组成,共同消费一个Topic,实现负载均衡和并行处理。 8. **ZooKeeper**:在早期版本中用于管理集群元数据、Broker注册、Leader选举等,但在新版本中Kafka逐步使用自管理的元数据机制(KIP-500)替代ZooKeeper。 #### 1. 分区(Partition)机制 分区是Kafka实现分布式处理和水平扩展的基础。每个分区在物理上对应一个文件夹,存储着该分区的消息日志(Log Segment)。分区机制带来以下优势: - **并行处理**:生产者可以将消息并发地写入不同分区,消费者也可以并行消费不同分区的消息。 - **水平扩展**:通过增加分区数量,可以提升Topic的整体吞吐量。 - **消息顺序性**:每个分区内的消息是有序的,但不同分区之间不保证顺序。 分区的数量在创建Topic时指定,后续可以动态增加(但减少分区需要谨慎,因为会影响消息路由)。 #### 2. 副本(Replica)机制 每个分区可以配置多个副本(通过`replication.factor`参数设置),副本分为Leader和Follower: - **Leader副本**:负责处理该分区的所有读写请求。 - **Follower副本**:从Leader副本异步拉取数据,保持与Leader的数据同步。 当Leader副本所在的Broker宕机时,Kafka会从ISR(In-Sync Replicas,同步副本集合)中选举新的Leader,确保分区可用性。ISR是指那些与Leader保持同步的副本集合(包括Leader自己)。 #### 3. 生产者负载均衡 生产者通过分区器(Partitioner)决定消息发送到Topic的哪个分区。默认的分区策略是: - 如果指定了消息Key,则对Key进行哈希(murmur2哈希算法),然后根据哈希值对分区数取模,确定目标分区。 - 如果未指定Key,则采用轮询(Round Robin)方式分配分区。 生产者支持异步批量发送,通过`batch.size`和`linger.ms`参数优化吞吐量。 #### 4. 消费者组(Consumer Group) 消费者组是Kafka实现横向扩展消费能力的关键机制: - 组内每个消费者实例可以独立消费一个或多个分区。 - 每个分区只能被组内的一个消费者实例消费,从而避免重复消费。 - 当消费者实例加入或离开组时,会触发重平衡(Rebalance),重新分配分区。 消费者通过向Broker发送心跳(`session.timeout.ms`控制)来维持自己的成员资格。如果消费者在配置的时间内未发送心跳,则会被认为已失效,触发重平衡。 #### 5. 数据存储与持久化 Kafka使用顺序写入(Sequential Write)和零拷贝(Zero-Copy)技术实现高吞吐: - 消息以追加(Append)方式写入日志文件,充分利用磁盘顺序读写性能。 - 日志文件被分成多个段(Segment),包括活跃段(Active Segment)和非活跃段。非活跃段在达到一定条件(时间或大小)后可被删除或压缩(Compaction)。 - 通过操作系统的页缓存(Page Cache)减少磁盘I/O次数。 #### 6. 高可用性保障 - **Leader选举**:依赖ZooKeeper(或Kafka Raft元数据模式)进行Leader选举。 - **数据可靠性**:生产者可通过设置`acks`参数控制消息的持久化级别: - `acks=0`:生产者不等待Broker确认,可能丢失消息。 - `acks=1`:Leader副本写入日志即确认,Follower副本尚未同步(若Leader宕机可能丢失消息)。 - `acks=all`:等待所有ISR副本都确认,消息最安全。 #### 7. 分布式协调 早期Kafka依赖ZooKeeper存储以下元数据: - Broker注册信息 - Topic和分区的配置 - ISR集合 - 消费者组的Offset(新版本已存储在内部Topic `__consumer_offsets`中) 从Kafka 2.8.0开始,引入了基于Raft协议的KRaft模式(KIP-500),允许Kafka完全脱离ZooKeeper运行,简化了部署和运维。 ### 总结 Kafka分布式架构通过分区机制实现水平扩展,副本机制提供高可用性,消费者组实现负载均衡,结合顺序写入、批量处理等优化技术,使其成为高性能、高可靠的消息队列系统。随着KRFT模式的成熟,Kafka架构更加简洁和自治[^1][^2][^3][^5]。 ```mermaid graph TD A[Producer] -->|Push Messages| B(Broker Cluster) B -->|Store Messages| D[Partition 1] B -->|Store Messages| E[Partition 2] B -->|Store Messages| F[Partition 3] G[Consumer Group 1] -->|Pull Messages| B H[Consumer Group 2] -->|Pull Messages| B D -->|Replication| D1[Replica 1-1] D -->|Replication| D2[Replica 1-2] E -->|Replication| E1[Replica 2-1] E -->|Replication| E2[Replica 2-2] F -->|Replication| F1[Replica 3-1] F -->|Replication| F2[Replica 3-2] ``` > **架构优势**: > - **高吞吐**:分区并行处理+顺序I/O > - **高容错**:副本自动故障转移 > - **可扩展**:动态增加Broker/分区 > - **持久化**:消息持久化存储(可配置保留策略) --- §§相关问题§§ 1. Kafka分区数量的选择依据是什么? 2. Kafka副本同步机制(ISR)是如何工作的? 3. 消费者重平衡(Rebalance)对系统性能有何影响?如何优化? 4. KRaft模式相比ZooKeeper有哪些改进? 5. Kafka如何保证消息的精确一次(Exactly-Once)语义?</think>### Kafka分布式架构深度解析 Kafka分布式架构是其高吞吐、低延迟能力的核心基础,其设计包含以下关键组件和机制: #### 一、核心架构组件 ```mermaid graph TD Z[ZooKeeper] --> B[Broker集群] P[Producer] --> B B --> C[Consumer Group] B -->|分区复制| R[Replica] C -->|分区分配| P1[Partition1] C -->|分区分配| P2[Partition2] ``` 1. **Broker集群** - 每个Broker是独立运行的Kafka服务实例 - 通过`broker.id`唯一标识(如0,1,2,...) - 集群规模可动态扩展(支持数千节点)[^1] 2. **ZooKeeper协调服务** - 管理集群元数据(Broker注册、Topic配置) - 监控Broker存活状态(心跳检测) - 实现Leader选举机制(故障转移)[^5] 3. **生产者(Producer)** - 支持异步/同步消息推送 - 消息路由策略: ```java // 默认分区策略(哈希取模) int partition = key.hashCode() % numPartitions; ``` 4. **消费者(Consumer Group)** - 组内消费者共享Topic订阅 - 每个分区仅被组内一个消费者消费 - 支持动态扩缩容(重平衡机制)[^2] #### 二、分布式核心机制 ##### 1. 分区(Partition)机制 - 每个Topic划分为多个分区(物理存储单元) - 分区特性: - **有序性**:分区内消息严格有序 - **并行性**:不同分区可并行处理 - **水平扩展**:通过增加分区提升吞吐 $$总吞吐 = \sum_{i=1}^{N} 分区_i吞吐$$ ##### 2. 副本(Replica)机制 | 副本类型 | 职责 | 读写权限 | |----------|--------------------------|----------| | Leader | 处理所有读写请求 | 读写 | | Follower | 异步复制Leader数据 | 只读 | | ISR | 与Leader保持同步的副本集 | - | - 数据同步流程: ```mermaid sequenceDiagram Producer->>Leader: 发送消息 Leader->>Leader: 持久化消息 Leader->>Follower: 异步复制 Follower-->>Leader: 确认复制 Leader->>Producer: 返回ACK ``` ##### 3. 高可用实现 **故障恢复流程**: 1. ZooKeeper检测Broker失效 2. 触发Controller选举(集群中首个启动的Broker) 3. 为新分区选举Leader(优先选择ISR中的副本) 4. 更新元数据并通知所有消费者[^3] #### 三、数据存储设计 1. **分段日志(Segment)** - 每个分区对应一组顺序写入的日志文件 - 文件命名规则:`起始offset.log` - 索引文件:`.index`(偏移量索引) + `.timeindex`(时间戳索引) 2. **零拷贝优化** ```java // 使用sendfile系统调用 fileChannel.transferTo(position, count, socketChannel); ``` - 数据直接从页缓存发送到网卡 - 避免内核态-用户态数据拷贝[^1] #### 四、分布式协调 1. **Controller选举** - 通过ZooKeeper临时节点竞争 - 职责:分区分配、Leader选举、集群扩缩容 2. **消费者重平衡(Rebalance)** - 触发条件: - 消费者加入/退出组 - Topic分区数变化 - 会话超时(默认45秒) - 分区分配策略:Range/RoundRobin[^2] #### 五、KRaft模式(去ZooKeeper) > 自Kafka 3.0起引入的元数据自管理架构 ```mermaid graph LR C[Controller节点] -->|Raft协议| M[Metadata日志] B1[Broker] --> M B2[Broker] --> M ``` - 核心优势: - 简化部署架构 - 提升集群稳定性 - 元数据读写性能提升4倍[^1] --- > **架构设计精髓**: > 通过$$水平扩展 = 分区 \times 副本 \times 消费者组$$的乘积效应,实现: > - 线性吞吐增长(百万级QPS) > - 毫秒级延迟(生产到消费) > - 99.99%高可用性[^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值