Kafka

Kafka×Protobuf スキーマ設計: フィールド番号と互換性の実務指針

2026-04-19
NicheeLab編集部

KafkaでProtobufを採用する最大の理由は、軽量なワイヤ形式と強い型付け、そしてスキーマ進化のしやすさにあります。ただし、その前提は「フィールド番号」を正しく扱うことです。

本稿では、Confluent Schema Registry を利用した一般的な実装を前提に、CCDAKの出題範囲に沿って、フィールド番号と互換性の安全運用を具体例で解説します。

KafkaでProtobufを使う理由とワイヤ形式の前提

ConfluentのProtobufシリアライザは、メッセージペイロードにマジックバイトとスキーマIDを付加し、Schema Registry と連携してスキーマ進化を安全にします。コンシューマはスキーマIDからスキーマを取得し、バイト列を解釈します。

Protobufはワイヤ上でフィールド番号を用います。番号が意味を持つため、番号の再利用や付け替えは後方互換性を破壊します。スキーマの見た目(フィールド名)よりも、実体(番号と型)が重要だと理解してください。

  • Schema Registry による互換性チェックを活用することで、本番前に破壊的変更を検知可能
  • Protobufの未認識フィールドは旧クライアント側で無視されるため、適切に設計すれば追加は安全に行える
  • ワイヤ形式は軽量。頻出フィールドは番号を小さくするとエンコード効率がよい

Kafka × Protobuf × Schema Registry の関係

MagicByte + SchemaID + Protobuf bytesLookup / RegisterProducer App(Protobuf Ser.)Consumer App(Protobuf Deser.)KafkaTopicSchema Registry(Schemas)

フィールド番号の設計原則

Protobufのフィールド番号は1〜536870911の範囲で、19000〜19999は内部予約のため使用不可です。番号はワイヤ互換性の核心であり、いったん公開したら変更しない・再利用しないが鉄則です。

番号にはエンコード上のコスト差があります。1〜15はタグが短く、頻出・必須に近いフィールドに割り当てると効率的です。将来の拡張を見越し、論理ブロックやチームごとに番号帯を計画的に確保しておくと運用が安定します。

  • 一度リリースした番号は再利用しない(削除時は reserved に入れる)
  • 高頻度アクセスのフィールドは番号1〜15を優先
  • 将来拡張用に未使用番号をあらかじめ確保(例: 100–199は拡張用)
  • 19000–19999は使用しない(Protobuf予約)
  • 型の変更やoneofへの移動は別番号の新フィールドで表現し、古い番号は非推奨→予約へ

.proto 例: 予約と追加のパターン

syntax = "proto3";
package com.example;

message OrderV1 {
  // 頻出フィールドは小さい番号
  int64 order_id = 1;
  string customer_id = 2;
  // 将来の状態コード
  int32 status_code = 10;
}

// 進化後
message OrderV2 {
  int64 order_id = 1;
  string customer_id = 2;
  // status_code を enum に置き換えたい → 新番号で追加
  // 旧 10 は非推奨 → 予約して再利用禁止
  reserved 10; // 旧: status_code
  // 名前も予約できる
  reserved "status_code";

  // 新しい enum ベースの状態。旧クライアントは未認識として無視
  OrderStatus status = 20;

  // フィールド削除時は [deprecated = true] → 後で reserved へ
  string note = 30 [deprecated = true];
}

enum OrderStatus {
  ORDER_STATUS_UNSPECIFIED = 0; // 0 はデフォルト
  ORDER_STATUS_PLACED = 1;
  ORDER_STATUS_SHIPPED = 2;
  ORDER_STATUS_CANCELLED = 3;
}

互換性モードと安全な進化パターン

Schema Registry の互換性モードは主に Backward / Forward / Full の3種類。Protobufでは「新フィールド追加(新番号)」は多くのケースで後方互換的です。旧コンシューマは未認識フィールドを無視するため、既存の読み取りは成立します。

破壊的なのは、番号変更・再利用、型変更、oneof への移動、enum 番号変更などです。見た目の名称変更はワイヤ上は成立しても、コード生成や検証で破綻しやすく、実務上は破壊的とみなすのが安全です。

  • 追加は新番号で。既存番号はそのまま維持
  • 削除は段階的に: 非推奨 → 参照停止 → reserved
  • 型を変えたい場合は新番号・新フィールドで併存期間を作る
  • enum は値の追加は可、番号の変更は不可
互換モード許容される変更例失敗する代表例
Backward新しい optional 相当のフィールドを新番号で追加; 既存フィールドの doc コメント更新既存フィールドの番号変更・再利用; スカラー型の変更(int32→string など)
Forward使わなくなったフィールドを非推奨→実質的な削除(新コンシューマが扱える)旧メッセージ必須相当の情報を削る(新→旧で読めない)
Full命名やコメントの微修正; 完全に独立な新フィールドの追加番号変更・再利用; oneof へ既存フィールドを移動; enum 番号の変更

削除・再利用・リネームの運用手順

削除や置換は段階的に進めます。いきなりフィールドを消すと旧アプリのコンパイルが通らず、あるいは互換性検証で落ちます。非推奨フラグ→利用停止→予約の順が安全です。

番号と名前の両方を reserved に入れることで、将来の誤再利用を防げます。スキーマ履歴を Schema Registry と一緒に運用し、PRレビューチェックに互換性検証を組み込むと事故が減ります。

  • Step1: 対象フィールドに deprecated を付与し、利用停止の告知
  • Step2: プロデューサが新フィールドへ完全移行するまで待機(並走期間)
  • Step3: 古いフィールドを .proto から削除し、番号・名前を reserved に登録
  • Step4: Schema Registry 上で互換性を Full(または組織標準)に固定し、破壊的変更をブロック

.proto で削除時に行う定型

message CustomerV2 {
  int64 id = 1;
  string email = 2;
  // 旧 phone は利用停止済み → 削除して予約
  reserved 5;           // 番号の再利用禁止
  reserved "phone";     // 名前の再利用禁止
}

oneof・map・enum の互換性の落とし穴

oneof にフィールドを追加すると、旧クライアントはその分岐を未認識として扱い、期待する意味論を満たせない可能性があります。Schema Registry の検証を通っても、アプリ互換性としては破壊的になりがちです。

map は内部的に繰り返しメッセージへ変換されます。キー・値の型変更は破壊的。enum は値の追加は安全ですが、値番号の変更や再割当ては破壊的です。名称変更はワイヤ上は許容でも、生成コードや読みやすさの観点から原則避けます。

  • oneof: 既存フィールドの oneof への移動は避ける(破壊的)
  • map: キー型の変更は不可。値型変更も不可。必要なら新フィールドで置換
  • enum: 値の追加は可、番号変更・再利用は不可。削除時は番号を reserved 相当として再利用禁止
  • 名称変更は最終手段。ワイヤ互換でもツールチェーン互換を壊すことがある

運用設定とCCDAK観点の確認ポイント

Subject Naming Strategy は再利用戦略に直結します。TopicNameStrategy(デフォルト、<topic>-value)、RecordNameStrategy(メッセージ型単位で共有)、TopicRecordNameStrategy(トピック×型)を要件に応じて選択します。

Protobufシリアライザ/デシリアライザはそれぞれ io.confluent.kafka.serializers.protobuf.KafkaProtobufSerializer / KafkaProtobufDeserializer を使用します。生成クラスを返したい場合は specific.protobuf.value.type を設定します。

互換性レベルはグローバルやサブジェクト単位で設定可能です。開発環境は Backward、プロダクションは Full を基本とし、破壊的変更をブロックする運用が無難です。

  • CCDAKチェック: 互換性モードの意味、許容/非許容変更例を即答できること
  • Subject Naming Strategy をケースで選べること(スキーマ再利用 vs 分離)
  • Producer/Consumer の Protobuf SerDe 設定と Schema Registry 連携を説明できること

Schema Registry とクライアント設定の例

# Producer/Consumer プロパティ(抜粋)
key.serializer=org.apache.kafka.common.serialization.StringSerializer
value.serializer=io.confluent.kafka.serializers.protobuf.KafkaProtobufSerializer
schema.registry.url=http://localhost:8081
# 型を返したい場合(例)
specific.protobuf.value.type=com.example.OrderV2
# Subject Naming Strategy を変更したい場合(例)
value.subject.name.strategy=io.confluent.kafka.serializers.subject.RecordNameStrategy

# 互換性モード設定(サブジェクト単位)
# Backward/Forward/Full などを指定
curl -X PUT -H "Content-Type: application/json" \
  --data '{"compatibility": "FULL"}' \
  http://localhost:8081/config/my-orders-value

問題で確認

CCDAK

問題 1

注文イベントの Protobuf スキーマで、これまで数値の status_code (番号10) を使っていました。今後は意味を明確にするため enum 型の status を導入したい。既存のコンシューマは段階的に移行する計画です。最も安全な対応はどれか?

  1. status を新しい番号で追加し、旧 status_code の番号10と名前を reserved にし、互換性モードは Full を維持する
  2. 番号10をそのまま使い、型だけを int32 から enum に変更する
  3. 旧フィールドの名前を status にリネームし、型は後で差し替える
  4. 一時的に互換性チェックを無効化してから番号10を新用途に再利用する

正解: A

最も安全なのは新番号で enum フィールドを追加し、旧フィールドは非推奨→reserved として再利用を防ぐ手順。番号の再利用や型変更は破壊的で、互換性チェックを無効化する運用も推奨されない。

よくある質問

フィールド番号は飛ばしてもよいですか?

問題ありません。将来の拡張やチーム間の分割に備えて余白を設けるのは有効です。特に1〜15は希少なので優先配分しつつ、次のブロックを空けておく運用が実務的です。

同じ番号でフィールドの型だけを変えるのは可能ですか?

不可です。番号はそのフィールドの同一性そのもので、型変更は破壊的です。新番号で新フィールドを追加し、旧フィールドは段階的に廃止してください。

Schema Registry なしでも Protobuf は使えますか?

技術的には可能ですが、互換性の自動検証やスキーマ配布ができず運用負荷が跳ね上がります。CCDAK および本番運用では Schema Registry の利用を前提に設計するのが無難です。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Kafka

Kafka Topic と Partition の基礎: 分散とスケーラビリティの要

CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...

Kafka

CCDAK 試験ガイド:出題範囲・配点・申込み・対策

Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...

Kafka

Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点

CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...

Kafka

Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性

レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...

Kafka

Kafka の Offset とコミット: ポジション管理と at-least-once の基礎

CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...

Kafkaの記事一覧 (101件)
© 2026 NicheeLab All rights reserved.