两个版本包一起发布:v1.5 —— 存储与生命周期v1.6 —— 运维、控制器与配额。二者合计为 Kafka Simulator 带来 19 个新场景,课程体系达到 122 个中的 74 个,自由模式也补齐了从 v1.3 开始搭建的集群形态阶梯。

这次我们从自由模式讲起,因为这两项解锁是被问得最多的。

自由模式:拓扑阶梯已经补齐

自 v1.3 起,沙盒每个版本包增加一种集群形态:先是主备,然后是双活。这两种都是由异步镜像连接的两个集群。而现在落地的两种形态属于另一类:跨数据中心拉伸的同一个集群,复制是同步的,ISR 本身就横跨广域网。

区别在出问题的那一刻就会显现:

  • 镜像成对的架构里,失去一个区域是一次故障切换:你提升另一侧,并接受镜像尚未复制过去的那部分损失。
  • 拉伸集群里,失去一个 DC 是一次复制事件:ISR 收缩,而你还能不能写入,完全取决于 min.insync.replicas

3-DC 拉伸(v1.5 新增)

三个数据中心,一个集群。默认沙盒在 dc-adc-bdc-c 中各放一个 broker 和一个控制器,broker 交错排列,因此轮询放置会把每个分区的副本分散到全部三个站点。三个分区,于是每个 DC 打开时都持有一个天然的 leader,因此布局展示的是跨 DC 的均衡领导权,而不是一个孤零零的分区。

这里只有一个横跨三个站点的 KRaft 仲裁组,而不是每个区域各一个。杀掉一个 DC,你失去三票中的一票;剩下的两票仍构成多数,集群依然能做出决策。

2.5-DC 拉伸(v1.6 新增)

最后一级:两个存放数据的数据中心,外加第三个**见证(witness)**站点,它只持有一张控制器选票,完全不存数据。

这就是 Confluent 的 MRC 形态。每个数据 DC 拥有2 个同步副本和 1 个 observer —— 同步集合 RF 为 4,min.insync.replicas 为 3。关于 observer 有两点:

  • 它们不计入 ISR,所以不会拖住 acks=all 的写入。一个跨广域网、还要为每次提交把关的副本会是延迟灾难;observer 则让你在不付出写入路径代价的前提下保有一份远端副本。
  • 当 ISR 跌破 min.insync.replicas 时,observer 可以被自动提升进 ISR 以恢复持久性。沙盒默认在 ISR 下跌时提升、DC 恢复时再降回;你也可以让它保持提升状态,或者关掉自动、完全手动操作。

见证站点与本次发布的控制器场景直接呼应。仲裁组需要奇数张选票,而为此买下第三个完整数据中心太贵 —— 所以你只买半个。场景 06.0.2(「KRaft 仲裁组」)的结尾正是见证站点要防止的那种故障;现在你可以在沙盒里搭出两种部署,对比着看。

至此,全部五种集群形态均已可用:单 DC、主备、双活、3-DC 拉伸、2.5-DC 拉伸。自由模式后续的解锁 —— v1.7 的故障实验室、v1.8 的 Kafka CLI 终端、v1.9 的治理 —— 都是新能力,而不是新形态。

和 v1.3 时一样的说明:讲解这些拓扑的灾备课程仍然要到 v1.8 才落地。形态先行是有意为之,好让你在场景开口讲述之前就有地方把想法试一遍。

在此期间如果你想读更多关于多区域架构的内容,SoftwareMill 的《Apache Kafka 灾难恢复与多区域架构指南》对这些形态所蕴含的取舍做了相当深入的梳理。值得在把玩沙盒时另开一个标签页放着。

场景

v1.5 —— 存储与生命周期(9 个场景)

Kafka 的日志不是一卷无限长的磁带。本模块分三组讲清记录写入之后会发生什么。

保留 —— retention.msretention.bytes 如何推进 log start offset,以及消费者请求一个已被保留策略删除的 offset 时会得到什么(OFFSET_OUT_OF_RANGE,以及随之而来的重置)。

压实 —— cleanup.policy=compact 如何为每个 key 保留最新值,同时保持 offset 不变并留下空洞;墓碑记录如何删除一个 key,以及 delete.retention.ms 作为宽限窗口,让消费者在删除被清除前有机会观察到它;还有 compact,delete 让两种策略同时运行。

分层存储 —— 把老化的日志前缀卸载到远端层、再读回来,以及本地保留与保留的区别。这一组最能改变你给集群做容量规划的方式:本地保留不再是限制消费者能回溯多远的那个因素。

v1.6 —— 控制平面(kraft,4 个场景)

控制器做什么,以及它不在时什么会停下:

  • 控制器的职责KRaft 仲裁组 —— 控制器保持一致的是元数据,不是数据。失去仲裁多数就没有控制器了:leader 留在原地,在有投票者回来之前任何新决定都做不出来。
  • 控制器故障切换与元数据追赶 —— 新的活跃控制器必须先追上已提交的元数据 offset 才能对外服务,这正是故障切换后选举会短暂冻结的原因。
  • ZooKeeper 对比 KRaft —— 同一个集群在两种控制平面下并排呈现。

v1.6 —— 运维(operations,6 个场景)

运维人员在线上集群里会改什么,以及每一项改动的代价:

  • 扩容及随之而来的再均衡;缩容,在移除 broker 之前先把它排空。
  • 手动分区重分配,以及负载下被限流的同一次重分配 —— 你会看到新副本因为你为保护线上流量而给它的追赶速率设了上限,从而更晚才加入 ISR。
  • 在线配置变更,以及通过延迟响应而非丢弃数据来限流生产者的客户端配额

接下来

122 个场景中的 74 个,已发布七个版本包,自由模式沙盒现在能够模拟课程体系后续会引用的每一种集群形态。接下来是 v1.7 与故障实验室:按需向这五种形态中的任意一种注入 broker 击杀与网络分区。

打开模拟器,启动一个 2.5-DC 沙盒,杀掉一个数据 DC,然后看着 observer 被提升上来,把你稳稳托在 min.insync.replicas 之上。