予約フィールドとフィールド番号管理
reserved宣言によるフィールド番号と名前の管理。フィールド番号の再利用が危険な理由、フィールドの安全な廃止方法、スキーマ進化のベストプラクティスを学びます。
Enums & Oneof
詳細な説明
Reservedフィールドによる安全なスキーマ進化
protobufメッセージからフィールドを削除する際は、そのフィールド番号と名前の再利用を防ぐ必要があります。異なる型でフィールド番号を再利用すると、古いコードと新しいコードが相互作用する際にデータ破損を引き起こします。
syntax = "proto3";
message UserProfile {
// 現在のフィールド
int64 id = 1;
string username = 2;
string email = 5;
string avatar_url = 8;
bool is_verified = 9;
// フィールド3, 4, 6, 7は過去のバージョンで削除
reserved 3, 4, 6, 7;
reserved "first_name", "last_name", "phone", "address";
// 範囲指定もサポート
// reserved 100 to 199;
}
Reservedが重要な理由
reservedなしのシナリオを考えてみましょう:
- バージョン1:
string phone = 3;— フィールド3は電話番号を含む文字列 - バージョン2: phoneフィールド削除、開発者が
int32 age = 3;を追加 — フィールド3は整数に - バージョン1でシリアライズされたメッセージをバージョン2が読み取る:電話番号の文字列が整数として解釈され、破損やクラッシュを引き起こす
reserved 3;を使用すると、コンパイラがフィールド番号3の再利用を許可しなくなり、コンパイル時にこのエラーを検出します。
予約名 vs 予約番号
- 予約番号はワイヤーレベルの破損を防止(最も重要)
- 予約名はJSONフォーマットの衝突とソースコードの混乱を防止
- ベストプラクティス: 削除されたすべてのフィールドの番号と名前の両方を予約
フィールド番号範囲
フィールド番号は有限のリソースです:
| 範囲 | 目的 |
|---|---|
| 1-15 | 1バイトタグエンコーディング — 頻繁にアクセスするフィールドに使用 |
| 16-2047 | 2バイトタグエンコーディング — 標準フィールド |
| 2048-536,870,911 | 3バイト以上 — まれに使用 |
| 19000-19999 | protobuf実装により予約 — 使用不可 |
廃止パターン
フィールドを即座に削除する代わりに、まず非推奨としてマークします:
message Config {
string name = 1;
string old_setting = 2 [deprecated = true];
string new_setting = 3;
}
ユースケース
複数のサービスバージョンが共存し、ローリングデプロイメント中のデータ破損を避けるために後方/前方互換性が不可欠な大規模組織での本番protobufスキーマの安全な進化。