Protobuf によるビデオメタデータの軽量化
当社のインジェストワーカーは、2時間ごとに数千件のトレンド動画を取得しています。このデータは、ランキングサービス、キャッシュウォーマー、および分析ジョブの3つのサービスに送信されます。
長い間、このデータの転送には JSON を使用していました。それは、問題が発生するまではうまく機能していました。
JSON では、ビデオレコード1件あたり 2.4 KB ありました。40,000 件のレコードを3つの異なるサービスに転送するということは、2時間ごとに 280 MB の冗長なテキストを転送することを意味していました。これにより帯域幅が浪費され、PHP ワーカーの処理速度が低下していました。
私たちは Protocol Buffers (Protobuf) に切り替えました。なぜそうしたのか、そしてそれがどのようにシステムを変えたのかを説明します。
JSON における3つの主な問題点:
- サイズ:JSON はすべてのレコードでフィールド名を繰り返します。"viral_score_24h" のようなフィールド名は、わずか 8 バイトの数値を運ぶためだけに 15 バイトを消費します。
- 解析コスト:サービスが2つのフィールドしか必要としない場合でも、PHP は JSON ブロブ全体を解析しなければなりません。
- スキーマの乖離(Schema Drift):JSON には契約(コントラクト)がありません。あるサービスがフィールドを変更すると、他のサービスは実行時に静かにエラーを起こします。
Protobuf がどのようにこれを解決したか:
Protobuf は名前の代わりにフィールド番号を使用します。また、単一の真実のソース(single source of truth)として .proto ファイルを使用します。このファイルから PHP、Python、Go 用のコードが生成されます。スキーマを変更すると、コードのコンパイルに失敗します。これにより、実行時のバグをコンパイル時のエラーに変換できます。
結果:
1週間にわたってこれらの変化を測定しました:
- ペイロードサイズ:2.4 KB から 720 バイトに減少(70%削減)。
- PHP エンコード時間:310 ms から 95 ms に短縮。
- Go デコード時間:140 ms から 38 ms に短縮。
- 帯域幅:1サイクルあたり 280 MB から 84 MB に減少。
Protobuf を使用すべき場面:
すべてに対して使用しないでください。ペイロードが小さい場合や、人間が簡単に読み取れる必要がある場合は、JSON を使い続けてください。速度と厳格な契約が最も重要となる、大量の内部トラフィックに対して Protobuf を使用してください。
当社のパブリック API は引き続き JSON を使用しています。内部サービスには Protobuf を使用しています。