kafka的核心点

95 阅读3分钟

一、Kafka 发送消息的 核心架构设计

flowchart LR
    Producer -->|1.选择分区| Broker
    Broker -->|2.写入Leader分区| Partition[(Partition)]
    Partition -->|3.同步副本| Follower1 & Follower2
    Broker -->|4.持久化| CommitLog[(顺序写磁盘)]
    Consumer -->|5.拉取消息| Broker

1. 生产者发送流程

  • 分区路由:根据hash(key)%分区数或轮询策略选择目标分区
  • 批处理缓冲:内存中的RecordAccumulator缓存消息,批次达到batch.size(默认16KB)或linger.ms(默认0ms)触发发送
  • 网络传输:使用NIO的Selector实现非阻塞IO,通过Sender线程异步发送

2. Broker存储设计

  • 日志分段:每个分区划分为多个LogSegment(默认1GB),包含.log数据文件+.index索引文件
  • 页缓存优化:利用Linux页缓存(Page Cache)避免JVM堆内存GC影响
  • 零拷贝传输:消费者读取时通过sendfile系统调用直读磁盘文件

二、Kafka 为什么快?

❶ 吞吐量优化设计

pie
    title 性能优化因素占比
    "顺序磁盘IO" : 40
    "零拷贝技术" : 25
    "批量处理" : 20
    "压缩算法" : 15

关键技术解析

  • 顺序写盘:消息以追加(Append)方式写入,机械磁盘吞吐可达600MB/s
  • 零拷贝:消费者读取时数据不经过用户空间,直接从内核缓冲区传输到网卡
  • 压缩算法:支持Snappy/Gzip/LZ4,降低网络传输量(如LZ4压缩率约50%)
  • 内存映射:通过MappedByteBuffer将磁盘文件映射到内存地址空间

❷ 精准一次(Exactly-Once)实现

sequenceDiagram
    participant P as Producer
    participant B as Broker
    P->>B: 发送消息 (PID=100, Sequence=5)
    B->>B: 检查Sequence连续性
    alt 新PID或Sequence连续
        B-->>P: ACK
    else 重复Sequence
        B-->>P: 丢弃消息
    end

实现机制

  • 幂等生产者

    props.put("enable.idempotence", "true"); // 启用幂等性
    

    每个生产者实例分配唯一PID,每条消息携带单调递增Sequence Number,Broker端缓存最近5个分区的序列号进行去重

  • 事务支持

    producer.beginTransaction();
    producer.send(record1);
    producer.send(record2);
    producer.commitTransaction(); // 提交跨分区原子写
    

    使用事务协调器(Transaction Coordinator)管理两阶段提交(2PC)


三、Kafka 高可用副本机制

❶ 副本分布策略

graph TD
    TopicA-P0 -->|Leader| Broker1
    TopicA-P0 -->|Follower| Broker2
    TopicA-P0 -->|Follower| Broker3
    TopicA-P1 -->|Leader| Broker2
    TopicA-P1 -->|Follower| Broker3
    TopicA-P1 -->|Follower| Broker1

核心规则

  1. 每个分区的副本分布在不同的Broker(由broker.rack感知机架分布)
  2. Leader处理所有读写请求,Follower异步/同步拉取数据
  3. ISR(In-Sync Replicas)列表维护与Leader同步的副本

❷ 副本同步过程

sequenceDiagram
    participant Leader
    participant Follower
    Leader->>Follower: 发送消息批次 (lastOffset=100)
    Follower->>Leader: 响应成功 (fetchOffset=100)
    Leader->>Leader: 更新HW(High Watermark)=100
    Follower->>Follower: 提交消息到本地Log

关键参数

  • replica.lag.time.max.ms(默认30s):Follower未同步则移出ISR
  • min.insync.replicas(默认1):最小ISR副本数,影响写入可用性

❸ 故障恢复机制

sequenceDiagram
    participant C as Controller
    participant B1 as Broker1(Leader)
    participant B2 as Broker2(Follower)
    B1--x B1: 宕机
    C->>C: 检测Leader失效
    C->>B2: 提升为新Leader
    B2->>B2: 更新ZooKeeper元数据
    C->>All Brokers: 广播Leader变更

关键过程

  1. Controller(通过ZooKeeper选举)监控Broker存活状态
  2. 从ISR中选择新的Leader(优先选择存活副本)
  3. 若ISR为空且unclean.leader.election.enable=true,允许非同步副本成为Leader

四、Kafka 优势总结

核心优势对比表

维度Kafka实现方案传统MQ(如RabbitMQ)
吞吐量单机百万级TPS(开启压缩/批处理)万级TPS
消息持久化磁盘存储支持TB级数据保留内存存储为主
水平扩展分区可动态增加,支持千级分区队列扩展困难
数据一致性通过ISR+HW机制保证副本一致性主从异步复制存在数据丢失风险

典型性能数据(单Broker测试)

xychart-beta
    title 吞吐量对比(消息大小1KB)
    x-axis ["Kafka", "RabbitMQ", "RocketMQ"]
    y-axis "TPS (万)" 0 --> 100
    bar [78, 12, 45]
    line [78, 12, 45]

五、Kafka的 最佳实践建议

  1. 分区规划

    • 目标吞吐量 = 单分区吞吐 * 分区数
    • 单分区极限:约10MB/s(未压缩)或 50MB/s(启用压缩)
  2. 可靠性配置

    acks=all                         // 等待所有ISR副本确认
    min.insync.replicas=2            // 最小同步副本数
    replication.factor=3             // 副本数
    
  3. 监控指标

    • Under Replicated Partitions(URP)应接近0
    • Leader选举次数(unclean选举需告警)

Kafka的"快"来源于体系化设计,而可靠性则建立在严密的副本同步机制上。这种速度与可靠性的平衡,使其成为现代数据管道的核心基础设施。