云原生 Kafka 架构演进:从分层存储到无盘化未来

2026-05-26 31 预计阅读时间:1 分钟
来源:infoq.com AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:11 分钟

Kafka 诞生于本地磁盘和固定集群的时代——Broker 持久化靠 JBOD,扩容靠手动加机器,成本靠"多买几块盘"硬扛。当事件流平台被搬上云,这套模型开始崩塌:存储成本远高于计算、Consumer 滞后时集群被迫保留海量冷数据、多租户隔离只能靠物理集群切割。分层存储、弹性 Consumer、Share Group、虚拟集群、FinOps 遥测,以及正在酝酿的无盘存储方案,正在从根本上重写 Kafka 的运维经济学。

分层存储:把冷数据从 Broker 磁盘卸载出去

传统 Kafka 的 log.retention.hours 本质上是在说——"不管数据有没有人读,Broker 都要在本地盘上扛这么久"。云上 SSD 每 GB 成本是对象存储的 10 倍以上,冷数据占着本地盘就是烧钱。

分层存储的核心思路:

  • 热层:最近写入的数据留在 Broker 本地 SSD,保证低延迟读写。
  • 冷层:超过阈值(时间或大小)的日志段被上传到 S3/GCS/Azure Blob,Broker 只保留元数据索引。
  • Consumer 读冷数据:Broker 从对象存储拉回所需段,缓存到本地后返回给客户端,客户端无感知。

这意味着 retention 可以从几天拉长到几个月甚至无限,而 Broker 本地盘只需要容纳热数据窗口。对 FinOps 来说,这是最直接的成本杠杆——把 80% 的存储支出从 SSD 转移到对象存储。

下面是一个 Kafka 分层存储的典型配置片段(基于 Confluent Platform 7.x+ 的 KIP-405 实现):

# tiered-storage.properties — Broker 端配置

# 开启分层存储
kafka.tier.feature=true
kafka.tier.enable=true

# 冷层后端:S3
kafka.tier.s3.bucket=my-kafka-tiered-bucket
kafka.tier.s3.region=us-east-1
kafka.tier.s3.aws.credentials.provider.class=software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider

# 热层保留策略:本地保留最近 4 小时或 1 GB
kafka.tier.segment.hotset.ms=14400000
kafka.tier.segment.hotset.bytes=1073741824

# 冷层归档后本地段删除
kafka.tier.archiver.max.tasks=4

# 长期 retention 放开(冷层在 S3 上保留)
log.retention.ms=2592000000   # 30 天

运行前需要确保 Broker 所在节点有 S3 访问权限(IAM Role 或 AK/SK),且 kafka.tier.feature=true 在集群范围内启用。

FinOps 遥测:让每一 GB 的成本可见

分层存储解决了"存哪里便宜"的问题,但 FinOps 要回答的是"谁在烧钱、烧在哪里"。云原生 Kafka 需要把存储、网络、计算的成本归因到具体的 Topic、Consumer Group 甚至租户。

实践中,这要求 Broker 端暴露细粒度指标,再通过 Prometheus + Grafana 或云厂商的 Cost Explorer 做关联分析:

# prometheus-kafka-cost-rules.yaml
# 用 recording rule 把 Kafka 指标和成本维度关联

groups:
  - name: kafka_finops
    interval: 60s
    rules:
      # 每个 Topic 的冷层存储量(GB)
      - record: kafka:tiered_storage_bytes:topic
        expr: |
          sum(kafka_tier_storage_bytes{topic=~".+"}) by (topic, cluster)
          / 1024 / 1024 / 1024

      # 每个 Consumer Group 的滞后量折算为热层占用
      - record: kafka:consumer_lag_cost:group
        expr: |
          sum(kafka_consumer_group_lag_records{group=~".+"}) by (group, cluster)
          * avg(kafka_log_segment_avg_bytes) / 1024 / 1024 / 1024

      # 标注成本标签(需要外部 label mapping)
      - record: kafka:cost_label:topic
        expr: |
          kafka:tiered_storage_bytes:topic
          * on(topic, cluster) group_left(cost_center, team)
          kafka_topic_cost_labels

有了这些 recording rule,Grafana 面板可以直接按 Team / Cost Center 展示"这个 Topic 在 S3 上每月花多少"、"这个 Consumer Group 的滞后导致热层多占多少 GB"。这才是 FinOps 的闭环——不是事后看账单,而是实时看指标做决策。

弹性 Consumer 扩容与 Share Group

Kafka 传统的 Consumer Group 模型有一个硬约束:一个 Partition 只能被同一个 Group 内的一个 Consumer 消费。这意味着 Consumer 并行度上限 = Partition 数。当流量突发时,你无法通过临时加 Consumer 实例来加速消费——除非你预先创建了足够多的 Partition,但那又会增加 Broker 端开销和延迟。

Share Group(KIP-932) 打破了这个约束:

  • 多个 Share Consumer 可以并发读取同一个 Partition 的不同消息批次。
  • Broker 端用"状态机"管理每条消息的交付状态(Ack / Nack / Redelivery),类似 JMS 的共享订阅。
  • Consumer 实例数不再受 Partition 数绑定,可以按流量弹性伸缩。

这对云原生场景至关重要——Consumer 可以用 Kubernetes HPA 按滞后量自动扩缩,而不是被 Partition 数卡住:

# kafka-share-consumer-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-processor
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-processor
  minReplicas: 2
  maxReplicas: 20
  metrics:
    - type: External
      external:
        metric:
          name: kafka_consumer_group_lag_records
          selector:
            matchLabels:
              group: order-processor-share
              topic: orders
        target:
          type: AverageValue
          averageValue: "5000"   # 每个 Pod 目标滞后 ≤ 5000 条
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
        - type: Percent
          value: 100
          periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300

注意:Share Group 目前是预览特性,生产使用前需确认你使用的 Kafka 版本和客户端 SDK 的支持状态。HPA 的 External metric 需要 Prometheus Adapter 把 kafka_consumer_group_lag_records 注册到 Kubernetes API。

虚拟集群:多租户的逻辑隔离

物理集群切割多租户是老办法——每个团队一个 Kafka 集群,运维成本爆炸。虚拟集群(如 WarpStream 的架构,或 Kafka 原生的 KIP-850 方案)在同一个物理集群上用逻辑命名空间隔离:

  • 每个虚拟集群有独立的 Topic 命名空间、ACL、配额。
  • Broker 端路由层根据客户端请求中的虚拟集群标识做隔离映射。
  • 底层存储和计算资源池共享,但配额和权限边界清晰。

这直接降低了控制平面成本——一个 9 Broker 集群可以服务 20 个虚拟租户,而不是 20 个 3 Broker 集群。

无盘存储:把 Broker 变成纯计算节点

分层存储已经把冷数据卸到了对象存储,但 Broker 本地仍然需要 SSD 做热层。无盘存储(Diskless Broker) 走得更远——Broker 完全不带本地盘,所有数据(包括刚写入的热数据)直接写入远程存储(S3 或分布式块存储),Broker 只做计算:协议解析、顺序保证、Consumer 协调。

架构上的变化和代价:

维度 传统 Broker 分层存储 Broker 无盘 Broker
写入路径 本地盘 → 刷盘确认 本地盘 → 异步上传 S3 直接写 S3/远程块存储
写延迟 ~1-5 ms(本地 SSD) ~1-5 ms(热层本地) ~10-50 ms(取决于远程存储)
Broker 有状态性 重,GB 级本地数据 中,热层 GB 级 轻,几乎无本地状态
扩缩速度 分钟级(数据迁移) 分钟级(热层迁移) 秒级(无数据迁移)
存储成本 高(全 SSD) 中(SSD + S3) 低(纯 S3/块存储)

无盘方案的核心吸引力是弹性——Broker 可以像无状态 Pod 一样秒级扩缩,因为不需要迁移本地数据。但代价是写入延迟的上升和架构复杂度(需要强一致远程存储或客户端确认机制的重新设计)。

目前 WarpStream、Confluent 的无盘预览方案都在探索这个方向,但生产级稳定性仍需验证。

落地路径与决策清单

从传统 Kafka 到云原生架构不是一步到位的,以下是分阶段建议:

阶段一:分层存储先行 - 优先开启分层存储,这是 ROI 最高的改动——存储成本通常立减 60-80%。 - 先在非核心 Topic 上验证 S3 后端的稳定性,再逐步扩大覆盖。 - 确保 FinOps 指标同步上线,否则你无法量化收益。

阶段二:弹性 Consumer - 在流量有明显波峰波谷的场景引入 Share Group + HPA。 - 评估客户端改造工作量——Share Group 需要新 SDK 或协议扩展。 - 先在可容忍少量重复消费的场景(如日志聚合)试运行。

阶段三:虚拟集群与多租户 - 当集群数量 > 5 时,认真评估虚拟集群方案。 - 配额和 ACL 必须先到位,否则一个租户的流量风暴会打穿共享资源池。

阶段四:无盘 Broker(观望+小规模验证) - 无盘方案目前适合对延迟不敏感、对弹性要求极高的场景(如日志管道、指标流)。 - 核心交易链路暂不建议,写入延迟和一致性的边界条件还需要更多实战验证。 - 可以先用分层存储 + 小热层窗口做"准无盘"——热层只保留 1-2 小时数据,Broker 重启后快速从 S3 恢复。

云原生 Kafka 的本质不是"把 Kafka 跑在 K8s 上",而是把存储和计算解耦、把成本归因到租户、把弹性从 Partition 数解放到 Pod 数。分层存储是第一步,无盘存储是终局方向——但中间每一步都有具体的工程取舍,值得按场景逐步推进。


相关推荐