未记录事实核验 · 状态:维护中

记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。

warning 适用边界与维护说明

本文适合用于 Topic 命名、容量估算、副本配置和扩容方案讨论;本次仅作全文结构审阅,未进行外部事实核验或命令实测。吞吐量与分区数量已明确为示例或待验证的规划假设,不应视为生产容量保证,场景分区数建议也需结合目标环境压测使用。配置默认值应以实际 Kafka 版本及集群配置为准,3 副本练习需至少 3 个 Broker。分区键一节的“保证处理顺序”应限定为分区数及路由规则稳定时的分区日志顺序,业务处理顺序仍取决于生产和消费方式;保留时长也不意味着单条消息到期即刻删除,compact 示例不宜理解为完整历史或所有最新状态的永久存档。 已取消无法确定目标的可点击引用「13-集群管理与运维」,保留原提及;Ambiguous link target: 13-集群管理与运维

主题与分区设计 - 像规划城市交通一样设计Topic

info 前置知识

Topic 和分区的设计是 Kafka 集群中最需要事先规划的决策,因为分区数只能增加不能减少,而错误的设计会在流量增长后引发难以修复的问题。本文提供可落地的计算方法和选型原则,不讲废话。


Topic 命名规范

好的命名规范有助于降低运维中的识别和沟通成本。推荐格式:

{环境}.{业务域}.{实体}-{动词/事件}

命名示例:

# 生产环境,电商域,订单创建事件
prod.ecommerce.order-created

# 测试环境,用户域,用户行为日志
test.user.behavior-log

# 支付域,交易成功事件
prod.payment.transaction-success

# DWD 层数仓 Topic(数据仓库管道常见用法)
dwd.user.profile-snapshot

# 死信队列(处理失败的消息)
prod.ecommerce.order-created.dlq

tip 命名规则清单

  • 只使用小写字母、数字、连字符(-)和点(.),避免下划线(下划线在某些监控工具中显示异常)
  • 包含环境前缀(prod/test/dev),防止生产和测试消息混流
  • 用动词或事件描述(order-created),而非名词堆叠(order-data)
  • 避免 topic、kafka、data 等无意义词汇
  • 死信队列统一加 .dlq 后缀

查看 Topic 信息的常用命令:

# 列出集群中所有 Topic
kafka-topics.sh --list \
    --bootstrap-server localhost:9092

# 查看某个 Topic 的分区分布和副本状态
kafka-topics.sh --describe \
    --topic prod.ecommerce.order-created \
    --bootstrap-server localhost:9092

# 查看 Topic 的覆盖配置(非默认值才会显示)
kafka-configs.sh --describe \
    --entity-type topics \
    --entity-name prod.ecommerce.order-created \
    --bootstrap-server localhost:9092

分区数规划

为什么分区数很重要

分区是 Kafka 并行处理的基本单位:

  • 一个分区同一时刻只能被消费者组内的一个消费者消费
  • 消费者的最大并行度 = 分区数
  • 分区数决定了 Producer 端的写入并行度(通过 Key 分区)

生活类比:把分区想象成高速公路的车道。车道越多,同时通行的车辆越多(吞吐量越高)。但车道也不是越多越好——车道太多而车辆少,会浪费基础设施,而且增加了 Broker 管理的开销(每个分区在 Broker 上对应一组文件)。

分区数计算公式

基于吞吐量的计算方式:

目标分区数 = ceil(max(
    目标生产吞吐量 / 单分区生产吞吐量,
    目标消费吞吐量 / 单分区消费吞吐量
))

容量计算的示例假设值(假设使用 SSD、100 字节消息、无压缩;下列数值不代表已提供依据的实测结果):

指标 参考值
单分区写入吞吐 ~10 MB/s
单分区消费吞吐 ~50 MB/s(示例假设值;zero-copy 可降低部分传输开销,但不保证消费吞吐高于写入吞吐)

计算示例:

某电商订单 Topic,峰值生产速率 100 MB/s,消费速率需匹配生产:

生产侧需要:100 MB/s ÷ 10 MB/s = 10 个分区
消费侧需要:100 MB/s ÷ 50 MB/s = 2 个分区(消费能力足够)
→ 基础分区数 = 10,再增加 30% 容量余量 → 至少设置 13 个分区,也可按部署需求选择 15 个分区

warning 分区数的上限问题

分区数不是越多越好。每个分区在 Controller 节点和每个 Broker 上都有元数据开销。可把单个 Broker 4000 个分区副本、整个集群 200,000 个分区作为待验证的规划假设,而非通用上限;适用范围取决于 Kafka 版本、控制器模式、硬件及负载。分区增多可能增加 Broker 重启和 Leader 选举的开销,应通过目标环境测试确定容量边界。

不同场景的分区数建议

场景 建议分区数 理由
日志收集(低 QPS,顺序不重要) 3~6 默认值,管理简单
业务事件流(中等吞吐,需要顺序) 12~24 按峰值 QPS 计算,留余量
大数据管道(高吞吐,TB 级) 48~96 对齐下游 Spark/Flink 任务并行度
需要全局有序的场景 1 单分区提供统一的日志写入顺序;业务事件顺序仍需生产和消费处理配合

分区扩容注意事项

warning 扩容会打乱 Key 的分区映射

Kafka 支持增加分区数,但不支持减少。更重要的是:增加分区后,相同 Key 的消息可能被路由到不同的分区(因为 hash(key) % partition_count 的结果变了)。这会破坏"相同 Key 的消息保证顺序"的语义。

扩容前必须确认:消费者是否依赖同 Key 消息的顺序?如果是,扩容需要配合消费者的状态迁移方案。

# 将 hello-kafka 的分区数从 3 扩容到 6
kafka-topics.sh --alter \
    --topic hello-kafka \
    --partitions 6 \
    --bootstrap-server localhost:9092

# 扩容后验证
kafka-topics.sh --describe \
    --topic hello-kafka \
    --bootstrap-server localhost:9092

副本因子选择

副本(Replica)是分区的完整拷贝,分布在不同 Broker 上。副本因子决定了数据冗余度和容灾能力。

选择原则

副本因子 适用场景 说明
1 开发/测试环境 无冗余,Broker 故障可能导致不可用,存储损坏时可能丢数据;不适合要求高可用和数据冗余的生产场景
2 对成本极度敏感,可容忍单点故障丢数据 单个副本故障后是否可继续写入取决于 ISR 状态、min.insync.replicas 和 acks;仅凭副本因子不能判断是否丢数据
3 生产环境标准配置 在 acks=all、min.insync.replicas=2 且剩余副本保持同步等条件下,可容忍 1 个副本所在 Broker 故障,兼顾成本和可靠性
5 金融、支付等强可靠性场景 在 acks=all、min.insync.replicas 不大于 3 且剩余副本保持同步等条件下,可容忍 2 个副本所在 Broker 同时故障,存储成本高

note 副本因子不能超过 Broker 数量

副本因子 ≤ 集群 Broker 数量。3 节点集群最多设 3 副本。新建 Topic 时,如果副本因子超过 Broker 数,命令会报错。

与 min.insync.replicas 的配合

副本因子单独配置意义有限,需要与 min.insync.replicas(最小同步副本数)配合:

副本因子 min.insync.replicas 含义
3 1 acks=all 时允许 ISR 最少仅有 Leader,但仍等待当前 ISR 中所有副本确认;ISR 缩至 1 时仅有单副本保障
3 2 acks=all 时要求 ISR 至少有 2 个副本,并等待当前 ISR 中所有副本确认
3 3 acks=all 时要求 ISR 有 3 个副本,并等待全部 ISR 副本确认;ISR 少于 3 时拒绝写入

生产推荐组合:副本因子 3 + min.insync.replicas=2 + acks=all

这个组合要求 ISR 至少有 2 个副本,并等待当前 ISR 中所有副本确认;单个副本所在 Broker 故障后,若剩余 ISR 仍满足要求且完成必要的选主,该分区可继续写入。


Topic 关键配置参数

Topic 级别的配置会覆盖 Broker 的全局默认值,可以针对每个 Topic 单独调整:

# 创建 Topic 时指定配置
kafka-topics.sh --create \
    --topic prod.ecommerce.order-created \
    --partitions 12 \
    --replication-factor 3 \
    --config retention.ms=604800000 \
    --config compression.type=lz4 \
    --config min.insync.replicas=2 \
    --bootstrap-server localhost:9092

# 对已有 Topic 修改配置(在线生效,无需重启)
kafka-configs.sh --alter \
    --entity-type topics \
    --entity-name prod.ecommerce.order-created \
    --add-config retention.ms=259200000 \
    --bootstrap-server localhost:9092

# 删除某项 Topic 配置(恢复为 Broker 默认值)
kafka-configs.sh --alter \
    --entity-type topics \
    --entity-name prod.ecommerce.order-created \
    --delete-config compression.type \
    --bootstrap-server localhost:9092

核心配置参数说明

数据保留相关:

参数 默认值 说明
retention.ms 604800000(7 天) 消息保留时长(毫秒),超过后被删除
retention.bytes -1(不限制) 分区最大字节数,超过后从最早消息开始删除
cleanup.policy delete 数据清理策略:delete(按时间/大小删除)或 compact(按 Key 保留最新值)
segment.bytes 1073741824(1GB) 单个日志段文件的大小,达到上限时滚动新文件
segment.ms 604800000(7 天) 强制滚动日志段的时间间隔(即使未达到大小上限)

性能相关:

参数 默认值 说明
compression.type producer(保持生产者压缩) Broker 端压缩算法:gzip/snappy/lz4/zstd/uncompressed
message.timestamp.type CreateTime 消息时间戳来源:CreateTime(生产者时间)或 LogAppendTime(Broker 写入时间)
max.message.bytes 1048588(~1MB) Broker 接受的最大记录批次大小;启用压缩时按压缩后的批次大小判断

可靠性相关:

参数 默认值 说明
min.insync.replicas 1 acks=all 时,至少需要多少副本在 ISR 中
unclean.leader.election.enable false 是否允许非 ISR 副本参选 Leader(允许则可能丢数据,禁止则可能短暂不可用)

典型场景配置示例

场景 1:业务事件流(高可靠,7 天保留)

retention.ms=604800000
compression.type=lz4
min.insync.replicas=2
unclean.leader.election.enable=false

场景 2:日志采集(大量写入,只保留 1 天)

retention.ms=86400000
retention.bytes=10737418240
compression.type=gzip
segment.bytes=268435456

场景 3:数据库变更日志(CDC,按 Key 压缩,永久保留最新状态)

cleanup.policy=compact
compression.type=snappy
min.insync.replicas=2

分区键的选择

分区键(Message Key)决定消息路由到哪个分区。默认策略是 hash(key) % partitionCount。

选择原则:

  • 需要保证顺序:用能代表"处理单元"的字段作为 Key。订单系统用 orderId,用户行为用 userId,这样同一订单/用户的所有消息进入同一分区,保证处理顺序。
  • 不需要保证顺序:可以不设 Key(实际路由策略取决于客户端版本和分区器配置,不一定逐条轮询),或用随机值,让消息均匀分布在所有分区,最大化吞吐量。
  • 避免热点 Key:如果某个 Key 对应的消息量远超其他 Key(比如用超级用户的 ID 作为 Key),会导致某个分区消息堆积而其他分区空闲,出现"数据倾斜"。此时可以给热点 Key 加随机后缀(userId + "_" + random(0,10)),将其分散到多个分区,代价是牺牲该 Key 的顺序保证。

掌握检查

  • [ ] 能够按吞吐量需求计算合理的分区数,并知道为什么不能无限增加
  • [ ] 理解副本因子与 min.insync.replicas 的关系,能解释"3 副本 + minISR=2"的含义
  • [ ] 掌握 retention.ms、cleanup.policy、compression.type 三个核心配置的使用场景
  • [ ] 知道分区扩容的限制(不可减少、Key 路由变化),能解释扩容前需要确认什么
  • [ ] 能够根据业务场景选择合适的分区键,并识别数据倾斜风险

实践练习

基础题:在本地集群创建一个 Topic test.order-events,要求:6 个分区,3 副本,消息保留 3 天,启用 lz4 压缩,min.insync.replicas=2。写出完整的 kafka-topics.sh 命令。

进阶题:假设一个用户行为 Topic 目前有 6 个分区,你需要将其扩容到 12 个分区。请描述:扩容之前需要与下游消费者团队确认哪些事情?扩容后消费者需要做哪些调整?


前置知识:消费者深入剖析 下一步学习:副本机制与一致性 - 深入理解 ISR、HW、LEO 等副本同步机制 相关文档:偏移量管理 | 性能调优实战 | 集群管理与运维