---
title: "Kafka Simulator v1.5 + v1.6 — 拉伸集群、存储与运维"
date: 2026-09-02T00:00:00.000Z
author: "michal"
excerpt: "两个版本包一起发布。自由模式以 3-DC 拉伸集群和 2.5-DC 见证站集群补齐了拓扑阶梯，19 个新场景覆盖日志的生命周期（保留、压实、分层存储），以及 KRaft 控制平面和对运行中集群的运维操作。"
---
两个版本包一起发布：**v1.5 —— 存储与生命周期** 和 **v1.6 —— 运维、控制器与配额**。二者合计为 [Kafka Simulator](/kafka-simulator/) 带来 **19 个新场景**，课程体系达到 **122 个中的 74 个**，自由模式也补齐了从 v1.3 开始搭建的集群形态阶梯。

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

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

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

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

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

### 3-DC 拉伸（v1.5 新增）

三个数据中心，一个集群。默认沙盒在 `dc-a`、`dc-b`、`dc-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 灾难恢复与多区域架构指南》](https://softwaremill.com/guide-to-apache-kafka-disaster-recovery-and-multi-region-architectures/)对这些形态所蕴含的取舍做了相当深入的梳理。值得在把玩沙盒时另开一个标签页放着。

## 场景

### v1.5 —— 存储与生命周期（9 个场景）

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

**保留** —— `retention.ms` 和 `retention.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 击杀与网络分区。

打开[模拟器](/kafka-simulator/)，启动一个 2.5-DC 沙盒，杀掉一个数据 DC，然后看着 observer 被提升上来，把你稳稳托在 `min.insync.replicas` 之上。