《Java 消息中间件·Kafka 内核与客户端》3.3 分区器与键设计
4.3.0 的默认分区逻辑不在 DefaultPartitioner 里,而在 BuiltInPartitioner:key 存在时用 murmur2 取模,key 为 null 时按字节粘性切换。本篇用 6 个分区的实测序列说明粘性批次、key 基数与热点 key 三种倾斜,并给出自定义 Partitioner 的完整写法和边界。
tag
4.3.0 的默认分区逻辑不在 DefaultPartitioner 里,而在 BuiltInPartitioner:key 存在时用 murmur2 取模,key 为 null 时按字节粘性切换。本篇用 6 个分区的实测序列说明粘性批次、key 基数与热点 key 三种倾斜,并给出自定义 Partitioner 的完整写法和边界。
acks=0 的成功只代表写进 socket,acks=1 的成功只代表 leader 写进本地日志,acks=all 才等到 ISR 确认。本篇用单节点杀 broker 的实验量出三种取值的失败窗口,拆开 retries 与 delivery.timeout.ms 的关系,并用批次头里的 PID 与 sequence 说明幂等生产者能去掉哪一种重复。
batch.size 是批次上限,linger.ms 是等待上限,compression.type 作用在整批数据上。本篇用五组参数和磁盘日志大小把三者的相互作用拆开:为什么批次满了 linger 就不起作用、为什么压缩率取决于批次而不是单条消息,以及 CPU 与带宽如何交换。
日志不会因为被读过就删除,它的生死由 cleanup.policy 决定。本节实测 delete 策略按时间整段回收,以及 compact 策略如何把同 key 的多次写入压成最后一条、墓碑如何先删除旧值、又为什么墓碑自己还要再等一轮清理,并给出两种策略的选择边界。
一个分区在磁盘上不是一个文件,而是一组按 base offset 命名的段。本节用两次真实写入制造时间滚动,拆开 .log、.index、.timeindex、.snapshot 的职责,解释 20 条记录为什么只产生 1 个索引项,并走一遍从 offset 到字节位置的寻址路径。
单节点能验证命令,三节点才能验证副本。本节先把 listeners、advertised.listeners 与 controller quorum 三组地址的分工讲透,再用真实的单节点启动日志和一个故意写错 advertised 的失败实验,解释为什么客户端连上了却读不到元数据,最后给出可直接使用的三节点 compose。
at-most-once、at-least-once、exactly-once 不是三个开关,而是三组失败窗口的取舍。本节先打出 4.3.0 的真实默认值,再分别复现「提交早于处理」的丢失、「处理完未提交」的重复、事务提交与 abort 的可见性,最后划清 exactly-once 只在 Kafka 读写链路内成立的边界。
5 条按顺序发出的消息,消费者看到的却是另一种顺序。本节用 3 个分区实测落点 1、2、2、0、1,从 murmur2 哈希与粘性分区讲到同 key 同分区,再把分区数的三笔代价——并行上限、文件与内存、故障恢复——逐条算清楚,并给出一个可操作的分区数估算顺序。
从队列、发布订阅、日志、流四种形态的差别入手,用单节点 Kafka 发 5 条消息、两个消费组读到不同位置、消费后日志段仍完整保留的实验,说明 Kafka 为什么选分区日志,以及「消费不删数据、位移是读者自己的进度」在工程上到底意味着什么。
本卷 15 章 45 节加两个附录,按「先建立直觉、再进服务端、再读客户端源码、最后做运维」的顺序组织。这篇目录给出完整章节索引、三条阅读路径、每章回答的具体问题、读之前需要的前置知识,以及哪些实验可以跳过,方便你按手上的故障或疑问直接跳读。
本书所有实验都在同一台机器上完成:Temurin 25.0.5+8、colima 里的 Docker 29.5.2、apache/kafka:4.3.0 的 KRaft 集群。这篇前言给出单节点与三节点两套底座的完整启动命令、客户端工程的最小 pom、源码核实方法,以及「单次运行不作基准」和「未在本机执行」两条数据口径的具体用法。
消息队列最常见的三类误判,是把「发了」当成「到了」、把「分区有序」当成「全局有序」、把「配了 acks=all」当成「不会丢」。本序用三个可以在本机复现的现象拆掉这三层幻觉,说明本书为什么坚持每个结论都要有命令和原始输出,并交代三卷各自回答什么问题。
《Java 消息中间件·Kafka 内核与客户端》全 50 篇:从分区日志的物理结构、副本与 ISR、KRaft 元数据,到生产者与消费者的源码走读、存储与零拷贝、压测与容量,最后落在运维动作、故障图谱与验收。单节点与三节点集群都在本机实跑,故障转移与 NOT_ENOUGH_REPLICAS 有原始输出。