🕹️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
不过也有几点需要注意⚠️
- 同一个partition只能被同一个消费者组的一个消费者消费
- 一个消费者可以消费多个partition
- 不同的消费者各自维护自己的offset
消费者组的优势
- 高可用:消费者故障后,不会影响整体的处理
- 高可扩展:消费者组内可以动态增加消费者
- 负载均衡:自动分配分区确保处理均衡
- 业务隔离:不同的消费者组互不影响
Session的理解
Session 代表了消费者组成员的一个消费会话,它包含了:
- 消费者组的成员身份信息
- 分区分配信息
- 消费位移(offset)管理
- 心跳检测机制
这段代码就代表了session的管理
在一下情况会发生session的重平衡(rebalance)
- 消费者加入组
- 消费者离开组
- 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 通过这种机制实现高可用性和数据一致性,确保即使部分节点故障,系统仍能正常运行。
水位线的理解

水位线分为高水位线和低水位线,图中还有一个日志末端位移的概念,即 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较高
适合开启压缩的场景:
- Producer和Consumer有充足的CPU资源
- 网络带宽资源有限
具体选择:
- 如果CPU资源充足但带宽受限:推荐使用zstd
- 如果要求高吞吐量:推荐使用LZ4
- 如果是一般场景:推荐使用Snappy
使用消息队列的好处是什么
1. 削峰填谷
缓冲突发流量,保证系统的稳定性,可以平滑的处理请求
2. 系统解耦
系统之间不直接依赖,易于系统扩展,降低系统耦合度
3. 提升可靠性
保证消息不丢失、消息不重复、消息最终会按序处理
4. 可扩展性好
若生产者这边数据很多,可以对应的增加消费者的数量,来加速消费
同样的,可以增加分区数量,来提升系统的吞吐量
业务功能的扩展
为什么kafka这么快
典型性能指标:
- 生产者吞吐量:数十万条消息/秒
- 消费者吞吐量:数十万条消息/秒
- 延迟:毫秒级
- 单机支持:数千个分区
1. 顺序写
利用磁盘的顺序读写特性,减少磁头寻道时间,来提高吞吐量
2. 零拷贝技术(Zero Copy)
减少数据拷贝次数,减少上下文切换,降低cpu使用率
3. 页缓冲区
利用操作系统的页缓冲区,减少磁盘I/O,提高读写性能
4. 分区并行处理
5. 文件分段存储

方便清理旧数据、提高查找效率、也便于文件管理
6. 批处理机制
减少网络请求次数、提高吞吐量,降低系统开销
实际生产中的性能优化
生产者优化
Broker优化
消费者优化
如何避免消息丢失
有三种场景会出现消息丢失
1. Producer端丢失
原因:
- 使用异步发送方式
producer.send(msg)
时采用"发射后不管"策略
- 网络抖动导致消息未到达Broker
- 消息不合格被Broker拒绝(如消息过大)
解决方案:
- 使用带回调的发送方式:
producer.send(msg, callback)
- 设置较大的重试次数:
retries > 0
- 在回调中处理失败情况:
- 对于瞬时错误:进行重试
- 对于消息格式问题:调整后重发
2. Broker端丢失
原因:
- Kafka使用异步批量刷盘策略
- 消息先写入PageCache,未及时刷盘时系统宕机会丢失
- 单个Broker的数据丢失是不可避免的
解决方案:
- 配置acks参数:
acks=all
:等待所有副本确认(最安全)acks=1
:仅等待leader确认(折中方案)acks=0
:不等待确认(不推荐)
- 关键Broker配置:
3. Consumer端丢失
原因:
- 自动提交导致未处理完就提交了位移,提交位移(offset)过早
- 多线程处理时的位移提交问题
解决方案:
- 关闭自动提交:
enable.auto.commit=false
- 采用手动提交位移,确保消息完全处理完成后才提交位移
如何做到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...