GO TechTalk #19 タクシーアプリ『GO』事業成長を支えるデータ分析基盤の継続的改善! で発表した資料です。
■ YouTube https://www.youtube.com/live/sD8IpwoIkaw?feature=share&t=735
■ connpass https://jtx.connpass.com/event/282134/
車両位置情報データの圧縮によるCloud Pub/Subのコスト削減2023.05.31牧瀬 芳太郎GO株式会社
View Slide
© GO Inc. 2自己紹介GO株式会社ソフトウェアエンジニア / 牧瀬 芳太郎タクシーアプリ『GO』データ基盤開発・運用などを担当Go言語でバックエンド開発もしています最近はゼルダの伝説ToKをプレイしていますが、寄り道しすぎてクリアに3ヶ月くらいかかりそう
© GO Inc. 3車両位置情報の収集▪ アクティブ車両台数: 数万台▪ 車両から送られる情報: GPS位置、方角、速度、メーター情報、etc.= 動態(車両動態)▪ 約9億レコード/日何に使われる?▪ 配車▪ 機械学習を使ったサービス▪ 到着時間予測 (DeNA TechCon 2022 にて紹介)▪ お客様探索ナビ (MoT TechTalk #10 にて紹介)▪ AI予約▪ etc.▪ サービス改善のための分析
© GO Inc. 4『GO』アプリ 動態パイプラインの全体図MoT TechTalk #7 技術書典頒布のタクシーアプリ『GO』アーキテクチャ図録を一挙解説にて紹介今回の話
© GO Inc. 5『GO』アプリ データ基盤のコスト▪ BigQuery についで Pub/Sub, Dataflow のコストが大きい▪ その中でも車両動態が多くを占める▪ データ流量に応じてかかるコストがあり、流量が多いためコストが高くなっている▪ 提携タクシーの増加に伴い、動態の流量は徐々に増加
© GO Inc.▪Pub/Sub 経由で BigQuery に投入▪Pub/Sub のペイロードは動態 1レコードの JSON6従来構成 (MoT TechTalk #12 にて紹介)ここの流量を減らしたい!
© GO Inc.▪Pub/Sub のペイロードを Protobuf + Zstandard に変更7新構成
© GO Inc. 8新構成Protobuf スキーマ ※実際より簡略化// 車両動態message AnalyticalThing {uint32 car_id = 1; // 車両IDdouble raw_lat = 2; // GPS緯度double raw_lon = 3; // GPS経度double speed = 4; // 速度Status.MeterStatus meter_status = 5; // メーター状態google.protobuf.Timestamp sampled_at = 6; // 取得日時.....}
© GO Inc. 9技術選定理由 データ形式Protocol Buffersを採用▪ Google社製のシリアライゼーションフォーマット▪ 動態配信システムから来るデータが元々 Protobuf 形式なので、そのまま流せば処理コストが少ない▪ 後段で圧縮するとしても、JSON より Protobuf を圧縮する方が最終的なサイズが小さくなる他に検討に上がった選択肢▪ Parquet, Avro 等→ 動態配信システムから来るデータが元々 Protobuf 形式なので、わざわざ変換するのは余計な処理が増えるだけなので不採用仮に動態配信システムから来るデータが Parquet や Avro 形式であったなら採用していた
© GO Inc. 10技術選定理由 圧縮アルゴリズムZstandardを採用▪ Meta(Facebook)社製の可逆圧縮アルゴリズム▪ リアルタイム処理性能を重視しており、GZIP と同程度の圧縮率で、より高速▪ JSON を Protobuf にするだけだとデータサイズ削減量が少ないため利用▪ 複数レコードをまとめて圧縮する。1台の車両からの動態データをある程度まとめて送ってもらっているため、似たようなレコードが多く効率的に圧縮できる他に検討に上がった選択肢▪ GZIP→ やや古いアルゴリズム。最近は同程度の圧縮率で、より高速なものがある
© GO Inc. 11Protobuf のレコードをまとめるときの工夫課題▪ Protobuf のレコードは可変長のバイナリデータ▪ レコード自体には区切りとなる情報がない工夫▪ レコードの長さを先頭に付与して連結する▪ トータルのレコード件数がいくつであっても、単にバッファ or ファイルの後ろに追記していけば良いため、ストリーミング処理と相性が良い
© GO Inc. 12実装Pub/Sub に投げる側: Go言語で書かれた内製ワーカー▪ 今までは Protobuf を JSON に変換していたが、Protobuf のまま複数レコードまとめて圧縮し publish するように変更▪ 圧縮処理は並列動作するように実装Pub/Sub から読み出す側: Dataflow▪ Mercari Dataflow Template を参考に独自にフレームワークの実装を行い、YAML 記述により様々な Beam API を呼び出せるようにし、柔軟にパイプライン定義ができるようにしている▪ 今回追加: Protobufデコード処理、ZStandard展開処理▪ フレームワークさえ修正すれば、各ジョブ定義自体はYAMLの書き換えだけで済む。YAMLの修正例は次ページにて説明
© GO Inc. 13実装: ジョブ定義YAMLの修正例--- laplace-vehicle-analytics-log-collector.yaml 2023-05-11 17:08:20+++ laplace-vehicle-analytics-v2-log-collector.yaml 2023-03-13 12:13:31@@ -2,10 +2,13 @@- name: pubsubmodule: pubsubparameters:- subscription: "projects/my-project/subscriptions/laplace-vehicle-analytics-subscription"- format: string+ subscription: "projects/my-project/subscriptions/laplace-vehicle-analytics-v2-subscription"+ format: pbpack+ compression: ZSTDtransforms:- - name: parsejson- module: parsejson+ - name: parseprotobuf+ module: parseprotobufinput: pubsubparameters:+ descriptorFile: ../proto/laplace/common.pb+ messageName: laplace.AnalyticalThing.....
© GO Inc. 14成果▪高いデータ圧縮率▪ 約1/15 (JSON→Protobuf で 1/3、ZStandard でさらに 1/5)▪コスト削減▪ 動態の Pub/Sub, Dataflow 流量コスト: 93% 削減▪ データ基盤全体のコスト: 10% 削減▪エンコード/デコードの処理が高速化▪ 2,000 レコードの処理が 43ms → 18ms (エンコード側)▪ CPU負荷が低い = マシンスペックが低く抑えられる
© GO Inc. 15まとめと所感まとめ▪ 車両動態を Pub/Sub に流すフォーマットをJSON → Protobuf+Zstandard に変更することによりデータ量を 1/15 にし、大幅なコスト削減を達成所感▪ Pub/Sub は流量が多いとコストがかさみやすい▪ (最近は BigQuery Subscriptions もあるが) あえて Dataflow を利用しデータ圧縮を行うことで流量を削減し、コストを抑えられるケースがある
文章・画像等の内容の無断転載及び複製等の行為はご遠慮ください。© GO Inc.