4. Schema Registry 选型与搭建:三大主流方案对比与本地实战

数据契约落地,绕不开一个核心组件——Schema Registry。说白了,它就是管理数据格式的“注册中心”。没有它,生产者和消费者各自为政,格式一乱,整个数据链路就崩了。

我这些年接触过的项目,从几十个 Topic 的小集群到上千 Topic 的大规模平台,几乎都离不开 Schema Registry。今天咱们就聊聊市面上最主流的三个方案:Confluent Schema Registry、Apicurio Registry、Hortonworks Registry。我会结合自己的踩坑经验,帮你选型,再带你把环境搭起来。

核心观点:选 Schema Registry 不是选功能最强的,而是选跟你现有技术栈最匹配的。兼容性、社区活跃度、运维成本,这三个维度比功能列表更重要。

三大 Schema Registry 架构对比 Confluent Schema Registry Kafka 原生集成 Avro / Protobuf / JSON Schema REST API + 兼容性策略 Kafka 存储 Schema 商业版需付费 Apicurio Registry CNCF 生态 / 云原生 Avro / Protobuf / OpenAPI REST API + GraphQL SQL / Kafka / 内存存储 开源免费 Hortonworks Registry HDP 生态 / 老牌 仅 Avro REST API Hive / HBase 存储 社区停滞

4.1 为什么需要 Schema Registry?

先问个问题:没有 Schema Registry 会怎样?

我见过一个真实案例。某团队用 Kafka 传递用户信息,生产者写了个 JSON 字段叫 userName,消费者那边解析的是 username。少了个大写 N,数据全丢了。排查了三天,最后发现是字段名不一致。

Schema Registry 就是来解决这个问题的。它提供三个核心能力:

  • 统一管理:所有 Schema 集中存储,生产者和消费者都从 Registry 拉取
  • 版本控制:每次变更都生成新版本,支持向前/向后兼容性检查
  • 运行时校验:数据写入 Topic 前,自动校验格式是否匹配

我的习惯:只要涉及跨团队的数据交换,我必上 Schema Registry。哪怕初期只有两个 Topic,也值得。因为后期加 Schema 的成本远高于一开始就搭好。

4.2 三大方案横向对比

市面上方案不少,但真正经过大规模生产验证的,就这三家。我列个表,你看一眼就明白差异了。

维度 Confluent Schema Registry Apicurio Registry Hortonworks Registry
所属生态 Confluent / Kafka 原生 CNCF / Red Hat Hortonworks (HDP)
支持的序列化格式 Avro, Protobuf, JSON Schema Avro, Protobuf, OpenAPI, AsyncAPI 仅 Avro
存储后端 Kafka Topic SQL, Kafka, 内存 Hive, HBase
兼容性策略 BACKWARD, FORWARD, FULL, NONE BACKWARD, FORWARD, FULL, NONE 有限支持
REST API 成熟稳定 完善 + GraphQL 基础
社区活跃度 高(商业驱动) 高(CNCF 孵化) 低(已停滞)
许可证 社区版免费 / 企业版付费 Apache 2.0 完全开源 Apache 2.0

4.3 选型建议

看完表格,你可能更纠结了。别急,我直接给结论。

  • 如果你在用 Confluent Kafka:无脑选 Confluent Schema Registry。原生集成,零额外运维成本。我第一个生产项目就是这么选的,三年没出过问题。
  • 如果你在云原生环境:选 Apicurio Registry。它跟 Kubernetes、Istio 配合得很好,而且支持 OpenAPI,适合 API 优先的团队。
  • 如果你还在用 HDP:建议尽快迁移。Hortonworks Registry 已经基本不维护了,我去年帮一个客户从它迁移到 Apicurio,过程虽然折腾,但结果是值得的。

避坑指南:我曾经见过一个团队,因为 Hortonworks Registry 免费就选了它。结果半年后遇到一个 Avro 兼容性 Bug,社区没人修,最后自己啃源码才搞定。选型时一定要看社区活跃度,别只看价格。

4.4 本地搭建实战:Confluent Schema Registry

好,理论说完了,咱们动手。我以 Confluent Schema Registry 为例,带你从零搭一套环境。为什么选它?因为它是目前生产环境最常用的方案,文档也最全。

4.4.1 环境准备

你需要准备:

  • Docker 和 Docker Compose(推荐 20.10+)
  • 至少 4GB 可用内存
  • Kafka 3.0+(我们会用 Confluent 社区版)

4.4.2 编写 docker-compose.yml

我习惯把 Kafka、ZooKeeper、Schema Registry 放在一个 Compose 文件里,方便本地调试。

version: '3.8'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.4.0
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - "2181:2181"

  kafka:
    image: confluentinc/cp-kafka:7.4.0
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1

  schema-registry:
    image: confluentinc/cp-schema-registry:7.4.0
    depends_on:
      - kafka
    ports:
      - "8081:8081"
    environment:
      SCHEMA_REGISTRY_HOST_NAME: schema-registry
      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: PLAINTEXT://kafka:9092
      SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8081

4.4.3 启动服务

docker-compose up -d

等个十几秒,检查一下服务是否正常:

curl http://localhost:8081/subjects

返回 [] 就说明 Registry 跑起来了。嗯,这里要注意,第一次启动如果 Kafka 还没就绪,Registry 会报连接拒绝。等 Kafka 完全启动后再试一次就行。

4.4.4 注册第一个 Schema

咱们注册一个用户信息的 Avro Schema:

curl -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  --data '{"schema": "{\"type\":\"record\",\"name\":\"User\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"},{\"name\":\"name\",\"type\":\"string\"}]}"}' \
  http://localhost:8081/subjects/user-value/versions

返回结果会包含版本号和 Schema ID:

{"id":1,"version":1}

4.4.5 验证兼容性

假设你想加一个 email 字段,先检查兼容性:

curl -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  --data '{"schema": "{\"type\":\"record\",\"name\":\"User\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"email\",\"type\":\"string\",\"default\":\"\"}]}"}' \
  http://localhost:8081/compatibility/subjects/user-value/versions/latest

如果返回 {"is_compatible":true},说明新 Schema 兼容旧版本。我建议每次变更前都做这个检查,避免线上事故。

个人经验:我习惯把兼容性检查写进 CI/CD 流水线。每次 Schema 变更都自动触发检查,不通过就不允许合并。这招帮我挡住了至少 5 次潜在的线上故障。

4.5 本地搭建实战:Apicurio Registry

如果你更倾向云原生方案,Apicurio 的搭建也很简单。它支持 SQL 存储,适合跟现有数据库集成。

4.5.1 使用 Docker 启动

docker run -p 8080:8080 \
  -e REGISTRY_STORAGE_KIND=sql \
  -e REGISTRY_STORAGE_DB_KIND=h2 \
  apicurio/apicurio-registry-sql:2.5.0.Final

启动后访问 http://localhost:8080,你会看到一个 Web UI。我个人觉得 Apicurio 的 UI 比 Confluent 的好用,搜索和过滤功能更顺手。

4.5.2 注册 Schema

curl -X POST -H "Content-Type: application/json" \
  --data '{"schema": "{\"type\":\"record\",\"name\":\"Order\",\"fields\":[{\"name\":\"orderId\",\"type\":\"string\"},{\"name\":\"amount\",\"type\":\"double\"}]}"}' \
  http://localhost:8080/apis/registry/v2/groups/default/artifacts

4.6 生产环境注意事项

本地搭建只是第一步。真正上生产,有几个坑你必须注意。

  • 高可用部署:Schema Registry 是无状态的,可以水平扩展。建议至少部署 2 个实例,前面加一层负载均衡。
  • 存储后端选择:Confluent 的 Schema 存在 Kafka Topic 里,Topic 的副本数要大于 1,否则 Registry 挂了就恢复不了。Apicurio 建议用 PostgreSQL,别用 H2。
  • 兼容性策略:默认是 BACKWARD,允许消费者先升级。如果你不确定,就用 FULL,最安全。
  • 监控告警:关注 Registry 的请求延迟和错误率。我遇到过 Registry 响应变慢导致整个生产者超时的案例。

曾经踩过的坑:有一次我把 Schema Registry 的 Kafka 存储 Topic 的 cleanup.policy 设成了 delete,结果历史 Schema 被自动清理了。新消费者拉不到旧 Schema,全线报错。记住,这个 Topic 一定要用 compact 策略。

4.7 小结

Schema Registry 选型,说白了就是看你的技术栈和团队能力。Confluent 适合 Kafka 重度用户,Apicurio 适合云原生团队,Hortonworks 建议放弃。本地搭建用 Docker 几分钟就能搞定,但生产环境一定要考虑高可用和监控。

嗯,这一章的内容就到这。你先把环境搭起来,注册几个 Schema 试试,感受一下兼容性检查的流程。后面章节我们会讲怎么把 Schema Registry 跟数据契约的发布订阅流程结合起来。