Kafka
Kafka
核心价值: 解耦 缓冲 异步通信 高吞吐
基本角色: 生产者 消费者 主题
生产者(Producer)
向Kafka里写数据的程序
消费者(Consumer)
从Kafka里读数据的程序
主题(Topic)
Kafka里组织数据的方式, 相当于一个"频道"或者"分类"
分区(Partition)
Kafka高性能的关键
一个主题可以被分成多个分区
为什么要分区?
- 并行处理: 多个分区意味着可以同时写入, 同时读取.
- 保证局部顺序: Kafka只保证同一个分区内的消息是按发送顺序存储的.
副本(Replica)
数据存在一台机器上是有风险的, 万一机器坏了, 数据就没了. Kafka通过"副本"机制解决这个问题.
每个分区都可以有多个副本, 其中一个叫 Leader, 其他叫 Follower. 生产者只往Leader写, 消费者只从Leader读. Follower在后台默默同步Leader的数据.
如果Leader所在的机器挂了, Kafka会自动从Follower中选一个新的Leader, 服务继续, 数据也不会丢(前提是配置得当). 这里有个关键概念叫 ISR(In-Sync Replicas), 意思是"跟得上节奏的副本". 只有那些和Leader数据同步的差不多的Follower, 才有资格被选为新的Leader. 这样能避免选出一个落后的副本导致数据丢失.
消费者组(Consumer Group)
多人协作读取数据. Kafka不是简单的一对一收发, 它支持"一对多"甚至"多对多"的消费模式, 靠的就是消费者组.
一个消费者组可以包含多个消费者实例. 它们共同消费一个主题, 但Kafka保证: 同一个分区在同一时间只能被组内的一个消费者读取.
如果消费者数量多于分区数, 比如有8个消费者但只有6个分区, 那多余的2个就只能"待业", 因为Kafka不允许一个分区被多个消费者同时消费(重复处理).
另外, 不同消费者组之间是完全独立的. 比如组A和组B都订阅了同一个主题, 那么组A的消费进度不影响组B, 两者都能完整拿到全部数据. 这非常适合多个业务系统各自处理同一份原始数据的场景.
偏移量(Offset)
消费者怎么知道自己上次读到哪儿啦? 靠的就是偏移量(Offset).
每个分区里的消息都有一个递增的编号, 从0开始.消费者每次读完一批消息, 就会记录下自己读到的最大偏移量. 下次重启时, 就从这个位置继续读,不会重复也不会遗漏.
Kafka默认会把消费者的偏移量自动存到一个特殊的内部主题(_consumer_offsets)里. 你也可以自己管理, 但一般没必要.
这里有一个常见误区: 偏移量是按分区记录的, 不是按整个主题.
持久化与日志结构
Kafka把消息持久化到磁盘, 而且性能还特别高.
秘密在于它的存储设计: Kafka把每个分区的数据写成一个"日志文件", 追加写入(append-only), 不修改已有内容.这种操作对磁盘非常友好. 再加上它利用操作系统的页缓存(page cache)和零拷贝技术, 读写效率极高. 而且, Kafka的消息默认会保留一段时间(比如7天), 即使消费者还没来得及处理, 数据也不会马上消失, 这让系统更有容错能力.
生产者如何保证可靠发送
虽然Kafka本身很稳, 但如果生产者发消息是网络抖动, 服务器挂了, 还是可能丢数据.
生产者有几种策略来提高可靠性:
- 确认机制(acks): 生产者可以设置发完消息后要不要Kafka确认. (acks=0 acks=1 acks=all)
- 重试机制: 如果发送失败, 生产者可以自动重试.
- 幂等性: Kafka支持"幂等生产者", 开启后及时重试也不会产生重复消息. 这是通过给每条消息加唯一ID实现的.
- 事物, Kafka还支持跨分区的事务, 确保多条消息要么全成功,要么全失败.
消费者如何避免重复或者遗漏
理想情况下, 消费者处理一条消息, 提交偏移量, 完美. 但现实中总有意外: 消费者处理到一半宕机了, 偏移量还没有提交, 重启后就会重新处理这条消息; 如果消费者先提交了偏移量, 再处理消息, 结果处理时崩溃了, 那这条消息就丢了. 建议: 先处理消息, 再提交偏移量. (这种情况可能导致重复消费, 但不会丢)
重复怎么办? 这就要求业务逻辑具备"幂等性". 另外, Kafka还提供了手动提交偏移量的选项, 让你更精细控制何时提交, 配合业务逻辑做到"恰好一次"(Exactly Once)语义, 但这需要额外设计.
Kafka适用场景和局限
虽然Kafka很强大, 但它不是所有场景都合适. 适合Kafka的场景:
- 高吞吐, 低延迟的数据管道(日志搜集, 监控指标)
- 需要解耦生产者和消费者的系统
- 需要多个系统消费同一份数据
- 需要回溯历史数据(比如重放最近24小时的日志)
不适合Kafka的场景:
- 需要严格一对一, 点对点的消息传递(RabbitMQ更合适)
- 消息非常大(Kafka设计是为大量小消息优化的)
- 需要复杂的路由规则
- 对消息延迟及其敏感

运维和监控
Kafka集群一旦上线, 就得持续维护.
有几个关键点:
- 集群规模: 几个Broker(kafak服务器) 分区怎么分布 副本因子设多少
- 磁盘和网络: Kafka吃磁盘IO和带宽, 得监控资源使用
- 消费者滞后(Lag): 如果消费者处理太慢, 积压的消息越来越多, 叫"lag太高", 可能拖垮系统
- ZooKeeper 或 KRaft(新版): 老版本Kafka依赖ZooKeeper做协调, 新版本(2.8+)开始支持用内置的KRaft协议,简化架构 生产速率 消费速率 请求延迟 副本同步状态
Kafka生态
Kafka已经不只是一个消息中间件了, 而是一个流数据平台, 围绕它有一整套生态工具.
- Kafka Connect: 用来和外部系统对接, 比如从 MySQL 同步数据到Kafka, 或者把 Kafka 数据写入 Elasticsearch
- Kafka Steams: 轻量级流处理库, 让你直接在应用里做实时计算, 比如统计没分钟点击量
- KsqlDB: 用SQL语法实时查询Kafka数据流