🕹️kafka学习笔记

type
status
date
slug
summary
tags
category
icon
password
Blocked by
Blocking
AI summary
 

kafka是什么

kafka是一个分布式的、基于日志流处理的系统,通过broker、topic、partition和replica的协同工作,实现了高性能、高可用和可扩展的消息传递,适合实时数据管道、日志收集、时间溯源等场景。
具体的使用,代码可以参考repo kafka- example
 

基础概念

Offset的理解

offset是消息在分区中的唯一标识,类似于数组中的索引,用来记录消费者当前的消费进度,消费者重启后可以从上次的位置继续消费;重平衡后,新的消费者也可以从新的位置开始消费。
 
最早的位置
最新的位置
设置手动提交
设置自动提交
 

消费者组的理解

消费者组是一组共同消费kafka topic的消费者集合(即同一个topic能被不同的消费者组的消费者消费),不同的业务可以消费同一个topic
不过也有几点需要注意⚠️
  1. 同一个partition只能被同一个消费者组的一个消费者消费
  1. 一个消费者可以消费多个partition
  1. 不同的消费者各自维护自己的offset
 
消费者组的优势
  1. 高可用:消费者故障后,不会影响整体的处理
  1. 高可扩展:消费者组内可以动态增加消费者
  1. 负载均衡:自动分配分区确保处理均衡
  1. 业务隔离:不同的消费者组互不影响
 

Session的理解

Session 代表了消费者组成员的一个消费会话,它包含了:
  • 消费者组的成员身份信息
  • 分区分配信息
  • 消费位移(offset)管理
  • 心跳检测机制
 
这段代码就代表了session的管理
 
在一下情况会发生session的重平衡(rebalance)
  1. 消费者加入组
  1. 消费者离开组
  1. topic增加partition
 

对于Broker的理解

Broker是kafka的核心服务器,主要包含以下功能
 
Broker分为 Controller 和 普通Broker
  • 集群中的一个Broker会被选为Controller负责分区leader的选举、管理集群成员的关系、处理集群配置的变更
  • 普通的Broker用于处理消费者和生产者的请求、存储消息数据、维护分区的副本
 

对于leader、follower和理解副本因子的理解(replication factor)

Leader

若分区有多个副本,那么生产者发送数据的对象以及消费者消费的数据的对象,这些都是Leader

Follower

若分区有多个副本,实时从生产者同步数据,保持和Leader数据同步,Leader发生故障时,成为新的leader的,这些都是follower

factor

replication factor(复制因子)是指一个分区在 Kafka 集群中拥有多少个副本(包括 leader 和所有的 follower)。它在主题(topic)创建时指定,例如 replication.factor=3 表示每个分区有 3 个副本。
  • 作用
    • 提高数据的可靠性和容错性。如果一个 broker 宕机,数据仍然可以通过其他副本访问。
    • 复制因子决定了系统可以容忍的 broker 故障数量。例如,复制因子为 3 时,最多可以容忍 2 个 broker 失效(假设分区分布合理)。
  • 注意事项
    • 复制因子不能大于集群中的 broker 数量。
    • 更高的复制因子会增加存储和网络开销,但提升了数据可靠性。

三者之间的关系

  • 一个分区的副本数量由 replication factor 决定。例如,replication factor=3 表示该分区有 1 个 leader 和 2 个 follower。
  • leader 负责读写,follower 负责同步并在必要时接替 leader。
  • Kafka 通过这种机制实现高可用性和数据一致性,确保即使部分节点故障,系统仍能正常运行。
 
 

水位线的理解

notion image
水位线分为高水位线和低水位线,图中还有一个日志末端位移的概念,即 Log End Offset,简写是 LEO。它表示副本写入下一条消息的位移值

高水位线(High Watermark )

  • 指一个partition的所有副本都已经同步到的offset,这也是消费者可以安全读取的最新消息位置
  • 消息写入leader的日志后,只有当所有的follower都同步了这条消息,高水位才会向前移动
  • 确保了消费者不会读取到未提交的数据,从而保证了数据的一致性

低水位线(Low Watermark)

  • 指日志分区中最老的、仍然保留的消息偏移量,这个和kafka的日志清理策略有关
  • kafka会定期清除日志,删除低于低水位线的消息,以释放空间
  • 低水位线的移动通常由配置参数(如 log.retention.hours 或 log.retention.bytes)控制
 
 
 

kafka中的压缩算法

压缩是一种用时间换空间的实现,具体来说就是用cpu时间去换磁盘空间或网络I/O传输
 
  • 吞吐量排序:LZ4 > Snappy > zstd/GZIP
  • 压缩比排序:zstd > LZ4 > GZIP > Snappy
  • 网络带宽占用:Snappy最多,zstd最少
  • CPU使用:压缩时Snappy较高,解压时GZIP较高

适合开启压缩的场景:

  1. Producer和Consumer有充足的CPU资源
  1. 网络带宽资源有限
具体选择:
  • 如果CPU资源充足但带宽受限:推荐使用zstd
  • 如果要求高吞吐量:推荐使用LZ4
  • 如果是一般场景:推荐使用Snappy
 

使用消息队列的好处是什么

1. 削峰填谷

缓冲突发流量,保证系统的稳定性,可以平滑的处理请求

2. 系统解耦

系统之间不直接依赖,易于系统扩展,降低系统耦合度

3. 提升可靠性

保证消息不丢失、消息不重复、消息最终会按序处理

4. 可扩展性好

若生产者这边数据很多,可以对应的增加消费者的数量,来加速消费
同样的,可以增加分区数量,来提升系统的吞吐量
业务功能的扩展
 

为什么kafka这么快

典型性能指标:
  • 生产者吞吐量:数十万条消息/秒
  • 消费者吞吐量:数十万条消息/秒
  • 延迟:毫秒级
  • 单机支持:数千个分区

1. 顺序写

利用磁盘的顺序读写特性,减少磁头寻道时间,来提高吞吐量

2. 零拷贝技术(Zero Copy)

减少数据拷贝次数,减少上下文切换,降低cpu使用率

3. 页缓冲区

利用操作系统的页缓冲区,减少磁盘I/O,提高读写性能

4. 分区并行处理

5. 文件分段存储

notion image
方便清理旧数据、提高查找效率、也便于文件管理

6. 批处理机制

减少网络请求次数、提高吞吐量,降低系统开销

实际生产中的性能优化

生产者优化
Broker优化
消费者优化

如何避免消息丢失

有三种场景会出现消息丢失

1. Producer端丢失

原因
  • 使用异步发送方式 producer.send(msg) 时采用"发射后不管"策略
  • 网络抖动导致消息未到达Broker
  • 消息不合格被Broker拒绝(如消息过大)
解决方案
  1. 使用带回调的发送方式:producer.send(msg, callback)
  1. 设置较大的重试次数:retries > 0
  1. 在回调中处理失败情况:
      • 对于瞬时错误:进行重试
      • 对于消息格式问题:调整后重发

2. Broker端丢失

原因
  • Kafka使用异步批量刷盘策略
  • 消息先写入PageCache,未及时刷盘时系统宕机会丢失
  • 单个Broker的数据丢失是不可避免的
解决方案
  1. 配置acks参数:
      • acks=all:等待所有副本确认(最安全)
      • acks=1:仅等待leader确认(折中方案)
      • acks=0:不等待确认(不推荐)
  1. 关键Broker配置:

    3. Consumer端丢失

    原因
    • 自动提交导致未处理完就提交了位移,提交位移(offset)过早
    • 多线程处理时的位移提交问题
    解决方案
    1. 关闭自动提交:enable.auto.commit=false
    1. 采用手动提交位移,确保消息完全处理完成后才提交位移
     

    如何做到exactly once的

    kafka中的 三种承诺

    所谓的消息交付可靠性保障,是指 Kafka 对 Producer 和 Consumer 要处理的消息提供什么样的承诺。常见的承诺有以下三种:
    • 最多一次(at most once):消息可能会丢失,但绝不会被重复发送。
    • 至少一次(at least once):消息不会丢失,但有可能被重复发送。
    • 精确一次(exactly once):消息不会丢失,也不会被重复发送。
    目前,Kafka 默认提供的交付可靠性保障是第二种,即至少一次
    这样虽然不出丢失消息,但是会导致消息重复发送
    Kafka 也可以提供最多一次交付保障,只需要让 Producer 禁止重试即可。
    这样一来肯定不会重复发送,但是可能会丢失消息。

    具体实现

    Kafka 分别通过 幂等性(Idempotence)和事务(Transaction)这两种机制实现了 精确一次(exactly once)语义。
    在 Kafka 中,Producer 默认不是幂等性的,但我们可以创建幂等性 Producer。它其实是 0.11.0.0 版本引入的新功能。指定 Producer 幂等性的方法很简单,只需要将Idempotence参数设置为true。
    底层具体的原理很简单,就是经典的用空间去换时间的优化思路,即在 Broker 端多保存一些字段。当 Producer 发送了具有相同字段值的消息后,Broker 能够自动知晓这些消息已经重复了,于是可以在后台默默地把它们“丢弃”掉
     
    但这只能保证单分区的幂等性。若想实现多分区的幂等性,可以使用kafka的事物。
    不过最好还是在consumer这端实现去重,防止重复消费。
     
     
     

    如何保证数据的一致性

    IPR和raft协议
    Prev
    版本控制规范
    Next
    MongoDB 总结
    Loading...
    Article List