零、吃透kafka一、Kafka 到底是干嘛的?核心定位Kafka = 高速消息队列 / 消息日志现实类比:小区快递驿站生产者 Producer:网购商家,不停往驿站扔快递(发消息)Broker:驿站仓库(Kafka 服务节点)Topic:快递货架分类,比如「生鲜货架」「衣物货架」,一类消息一个 Topic消费者 Consumer:你本人,去驿站取快递(读消息)它最核心灵魂:把所有消息永久按顺序存成日志,支持海量、高并发读写,解耦系统。普通 MQ(RabbitMQ)取完消息默认删掉;Kafka消息不会自动删,这是所有概念的根源。二、最核心基石:分区 Partition(重中之重)一个 Topic 不是一整块存储,会切成多个分区。 类比:生鲜货架分成 1、2、3 号小格子(分区)顺序只保证分区内有序消息只会追加到分区末尾,同一个分区里消息先来后到不乱;但不同分区之间消息顺序无法保证。分布式扩容一台服务器存不下海量消息,多个分区分散在多台 Broker,横向提升并发、存储。副本 Replication(高可用核心)每个分区不止存一份,会复制多份副本。主分区(leader)负责读写,备用(follower)同步数据。leader 宕机,备用自动顶上,消息不丢。三、Offset 偏移量:所有 earliest/latest 的根源(你最难理解的点)每个分区里,每一条消息都有一个唯一递增数字编号 = offset类比:1 号格子(分区)快递,第 1 件 offset=0,第 2 件 offset=1,第 3 件 offset=2…… 不断往后加,永远只追加不修改、不插入中间。关键:消费者读消息靠 offset 标记读到哪了消费者读完消息后,会记录「这个分区我读到 offset=5 了」,下次重启从 5 之后接着读。 这里就诞生了你看不懂的earliest/latest/none,三个是重置 offset 策略:1. auto.offset.reset = earliest白话:从头读场景:消费者从来没记录过 offset(第一次消费),或者之前存的 offset 对应的消息已经被删了。 指令:直接跳到这个分区最小的 offset(最开头第一条消息),从头把所有存量消息全部读一遍。 举例:货架格子里有 100 个快递,你是新用户,earliest 直接从第 0 件开始全部取。2. auto.offset.reset = latest白话:只读新来的,历史旧消息不要新消费者无 offset 记录时,直接跳到分区当前最大 offset 的下一位,只等以后新产生的消息,历史存量全部忽略。 举例:货架已经堆了 100 件快递,你只等以后新发的 101、102,前面 100 件不看。3. none(极少用)没有 offset 且存在历史消息时,直接抛异常,不让程序自动重置,需要手动处理 offset。补充:offset 存在哪?消费者组 Consumer Group多个消费者组成消费者组,同一组内:一个分区只能分配给组内一个消费者(保证不重复消费);offset 是消费者组维度保存的。 举例子: 组 A 设置 earliest 从头读,组 B 设置 latest 只读新消息;两个组互不干扰,各自记录自己读到哪。 这就是 Kafka 支持多端重复消费同一份消息的核心原理。四、为什么要有缓存?Kafka 两层缓存(页缓存 + 批量缓存)Kafka 性能碾压其他 MQ,全靠缓存机制,分两种,分开讲人话:1. OS 页缓存(操作系统缓存,最核心)Kafka 本身不管理内存,消息直接存在磁盘文件。 操作系统会自动把经常读写的磁盘数据,缓存到服务器内存(页缓存)。 类比:书架(磁盘),你常看的几本书放桌面(内存缓存),不用每次弯腰翻书架。 优势:写消息:只写到内存缓存就返回成功,后台异步刷磁盘,速度极快;读消息:热点消息全在内存,几乎不走慢速磁盘。2. Kafka 批量缓存(Producer 生产者缓存)生产者发消息不会一条一条立刻发(网络开销极大),本地有缓存池: 攒一批消息 / 到指定时间,打包一次性发给 Broker。 两个参数控制:batch.size:攒满多少字节批量发送;[linger.ms](linger.ms):哪怕没攒满,最多等多久强制发送。作用:减少网络 IO,千万条消息发送速度提升几十倍。3. Broker 端缓存(分区索引缓存)每个分区日志配套索引文件,记录 offset 对应磁盘文件位置,索引常驻缓存。 消费者要读 offset=1000 的消息,不用遍历整条磁盘日志,索引一秒定位,查询超快。五、再梳理 Kafka 四大核心特性(总结核心)顺序日志存储:消息只追加、不修改,offset 唯一标记每条数据,消息持久化磁盘不自动删除;分区分布式:Topic 拆分多分区,实现扩容、并发读写、分区内有序;副本高可用:分区多副本,宕机不丢数据;多消费组隔离:不同消费组独立保存 offset,可重复消费,earliest/latest 控制首次读取起点;双层缓存提速:操作系统页缓存 + 批量批量缓存,做到磁盘级存储却拥有内存级速度。六、完整场景串一遍,打通所有概念需求:业务日志实时收集到 Kafka,两套程序消费服务程序(生产者)产生日志,本地批量缓存,攒一批发给 Topic=log_topic;log_topic 分 3 个分区,每个分区 3 副本,分散在 3 台 Broker,消息追加到分区末尾,分配 offset;第一套程序(消费组 A):需要同步全部历史日志,配置auto.offset.reset=earliest,第一次启动直接从分区最开头 offset 读取所有存量日志;第二套程序(消费组 B):只需要实时新日志,配置latest,启动后忽略历史,只接收后续新增日志;所有读写依靠服务器 OS 页缓存,大部分操作不碰磁盘,百万级消息秒级处理。七、常见疑惑一句话解答为什么不能所有消息全局有序? 答:Topic 分多分区,消息分到不同分区并行写入,只能保证单个分区有序。消息什么时候会消失? 答:不会自动删,靠配置retention.ms保留时长,到期后台清理旧消息;清理后旧 offset 失效,消费者此时会触发 earliest/latest 重置。offset 可以手动改吗? 答:可以,运维能手动重置 offset,用来重跑数据、跳过脏数据。缓存会不会丢数据? 答:生产者可配置 acks=all,等待所有副本落盘再返回,防止内存缓存未刷盘机器断电丢消息,兼顾性能与可靠性。一、搭建kafka环境1.1、docker安装kafka1.1.1:创建网络