Slide 1

Slide 1 text

1 バッチとストリーミング、 それぞれの障害に立ち向かう Data Engineering Study #4 @syu_cream

Slide 2

Slide 2 text

2 データエンジニア at メルペイ
 メルカリ・メルペイのデータ基盤整備人
 @syu_cream


Slide 3

Slide 3 text

3 それぞれの障害に立ち向かう バッチとストリーミング、

Slide 4

Slide 4 text

4 - バッチ処理 - 明確なデータの区切りが与えられる - 高スループット重視の処理がしやすい - データベースやファイルが入力になることが多い - ストリーミング処理 - 無限に続くデータ(アクセスログとか)を扱う - 低レイテンシが求められる際によく採用される - メッセージキューが入力になることが多い バッチ処理か、ストリーミング処理か

Slide 5

Slide 5 text

5 - バッチ処理 - コンピュート: Spark, Beam, Embulk, … - 入出力: HDFS, S3, GCS, MySQL, Aurora, Spanner, … - クラウドサービス: AWS Glue, Cloud Dataflow, … - ジョブスケジューラ: Airflow, Luigi, DigDag, ... - ストリーミング処理 - コンピュート: Spark, Flink, Beam, Kafka, Fluentd, … - 入出力: Kafka, Kinesis Data Streams, Cloud Pub/Sub, … - クラウドサービス: Kinesis Data Analytics, Cloud Dataflow, ... バッチ・ストリーミングの周辺エコシステム

Slide 6

Slide 6 text

6 - 利点 - 柔軟なワークロードに対応できる - バッチとストリーミング処理を混在できる - 欠点 - 障害点が増える、運用コストが増える <= !!! - それぞれ異なるフレームワークやインフラのノウハウが求められる - 開発コストが増える 2系統のシステムを持つ利点と欠点

Slide 7

Slide 7 text

7 バッチとストリーミング、 それぞれの障害に立ち向かう

Slide 8

Slide 8 text

8 ● コンピュート ○ Cloud Dataflow ● 入力 ○ Spanner, CloudSQL, ... ● 出力 ○ BigQuery ● スケジューラ ○ Airflow メルカリのバッチ処理基盤 https://engineering.mercari.com/blog/entry/2019-06-05-120000/ (現在は少しアーキテクチャ変更済み)

Slide 9

Slide 9 text

9 - ETL 負荷軽減のため updated_at カラムで差分更新 - レコード数が膨大なテーブルを毎回フルスキャンするのは非現実的! - 最後の同期時刻を Airflow の Variable に格納し、次回に WHERE 句で期間を絞り込む バッチ1: 差分更新で歯抜けになるレコード問題(1/3) id name ... updated_at 1 A 2020-10-01 ... N-1 Y 2020-10-31 N Z 2020-11-01 id name ... updated_at 1 A 2020-10-01 ... N-1 Y 2020-10-31 id name ... updated_at N Z 2020-11-01 schedule w/ “2020-10-31” SELECT … WHERE update_date >= “2020-10-31” +

Slide 10

Slide 10 text

10 - updated_at がうまく更新されていないケースがあった - e.g. DML 手動実行で、差分更新で保持する時刻より前の時刻に updated_at を指定 - 結果的に BigQuery 上では更新されない古いままのレコードが発生 - 現状は手軽な解決策なし!後で回復可能なので救いはあるが ...? バッチ1: 差分更新で歯抜けになるレコード問題(2/3)

Slide 11

Slide 11 text

11 - 差分レコードが BigQuery にロードされない問題 - 抽出した差分がロードの対象から漏れる? - 読み取った差分と既存レコードに重複がある場合は新しい差分を優先することで一旦解決 - なぜ差分が生まれ、なぜそれがロードされてないかは未解決課題 ... バッチ1: 差分更新で歯抜けになるレコード問題(3/3)

Slide 12

Slide 12 text

12 - ジョブスケジューラとして Cloud Composer を利用(していた) - A fully managed Apache Airflow - お手軽に環境構築、 gcloud cmd に統合された操作 - 割と頻繁にインフラ改善やアップデートが入る印象があった バッチ2: Cloud Composer の WebUI が停止(1/3)

Slide 13

Slide 13 text

13 - Airflow の webserver が頻繁に高負荷になり 502 が連発した - webserver が死んでると、 DAG 失敗時の調査やリトライが困難 - ^ cli でもできるがやりにくい。ワークフロー管理とは??? - このエラー 1000 回くらい見た。 30 sec 後に復旧した経験はない ... バッチ2: Cloud Composer の WebUI が停止(2/3) Error: Server Error The server encountered a temporary error and could not complete your request. Please try again in 30 seconds.

Slide 14

Slide 14 text

14 - 最終的に自前管理の GKE クラスタ上に Airflow を構築した - ユースケースが高度化してきて Cloud Composer がマッチしなくなってた - Config files から動的に DAG 生成とかしまくってた - デプロイや監視を考えると、自社のエコシステムを再利用できる方が嬉しかった - webserver のスペックを強めにして解決! - Cloud Composer も良くなっている - webserver を自前管理できるようになったらしい - https://cloud.google.com/composer/docs/how-to/managing/deploy-webse rver?hl=ja - webserver のスペックを変更できるようになったらしい (beta) - https://cloud.google.com/composer/docs/how-to/managing/creating?hl=ja #beta_features バッチ2: Cloud Composer の WebUI が停止(3/3)

Slide 15

Slide 15 text

15 ● コンピュート ○ Cloud Dataflow ● 入力 ○ Cloud Pub/Sub ● 出力 ○ GCS, BigQuery メルカリの(少し前の)ストリーミング処理基盤 https://speakerdeck.com/syucream/production-ready-stream-d ata-pipeline-in-merpay-inc (現在は結構アーキテクチャ変わってしまってる!)

Slide 16

Slide 16 text

16 - 元々はメルペイのマイクロサービスのログ収集パイプラインだった - 転用できそうだったのでメルカリでも利用 - ついでに API Gateway の役割をするマイクロサービスのアクセスログ収集にも利用 - 過去に想定してたトラフィック量と異なりすぎて処理が詰まりまくる - Pub/Sub の max unacked age が 5 days とかになる - Pub/Sub は 7 days 超えるとメッセージが消滅する ... ストリーミング1: 扱うトラフィックの増大(1/2)

Slide 17

Slide 17 text

17 - ログの種類で処理系を分ける - メッセージを集約しない、ジョブを分割する(高負荷のパスは高スペックで処理) - ストリーミングを諦めてバッチ処理に戻す - パース処理と BigQuery へのロードは現在 hourly バッチジョブ... - 根本的に作り直す - 最近 Apache Flink on k8s で再構築済み - https://events.mercari.com/gears-lecture/ で活動内容紹介してます ストリーミング1: 扱うトラフィックの増大(2/2)

Slide 18

Slide 18 text

18 - トラフィック増に加えて課金も増大していった - ログを永続化するだけでかなりのコストになっていた - Dataflow のデータ処理量、 Pub/Sub の課金が多かった - 中間データ表現を見直した - Avro の GenericRecord データが 1 レコード毎にスキーマがつく内容になっていた - スキーマ解決の仕組みを再構築してスキーマ分の冗長なトラフィックを削除した ストリーミング2: 課金の増大

Slide 19

Slide 19 text

19 - バッチとストリーミング、両アプローチを採用するケースは多々ある - 目的に従って、最適な技術を選択する - 両アプローチは異なるノウハウを要求し、障害のパターンも異なる - バッチとストリーミングで起こるそれぞれの障害に立ち向かおう - アーキテクチャ全体を見渡して問題を切り分けていこう - 障害を克服するため、恐れずにアーキテクチャを刷新していこう まとめ

Slide 20

Slide 20 text

20 - バッチ処理での障害 - 依存するクラウドサービスでの障害で機能しないケースが多い - Dataflow, GCE の障害の影響を受けて ETL ジョブが完全停止 - API Discovery Service という意外なやつに Airflow が依存しててジョブ失敗 - データソースとシンクの型のミスマッチで ETL が壊れる問題 - 古い JDBC Java Connector で一部 NULL が扱えなかったり - Timestamp 型の値が不正だったり - ストリーミング処理での障害 - スキーマ更新と BigQuery Streaming Insert - 2018 年頃は Streaming Insert を利用していた - スキーマ更新の際に table の patch API とか Beam job から呼んでたりした - スキーマの互換が取れなくて無限にリトライ -> quota にハマる地獄があった おかわり話題(時間が余った時にでも)