UberEats に広告を導入した後、Uber はいくつかの困難に直面した。生成したイベントは、迅速、確実、正確に処理する必要があった。これらの要件は、広告イベントのストリームを正確に1回のセマンティクスでリアルタイムに処理する、Apache Flink、Kafka、および Pinot をベースにしたシステムによって満たされた。このアーキテクチャを説明する記事が最近 Uber Engineering ブログに公開された。
著者は、広告イベントの処理で、データを失うことなく、またそれらを何回も評価することなく、可能な限り最小の遅延で結果を公開しなければならなかったと説明している。これらの要件は、Apache Flink、Kafka、および Pinot の助けを借りて構築されたソリューションによって満たされた。このシステムは、Kafka トピックを介して通信し、エンドユーザデータを Hive と Pinot に保存する Flink ジョブで構成されている。
著者によると、システムの信頼性は、クロスリージョンの複製、Flink チェックポイント、および Kafka の記録保持ポリシーに依存することによって保証されている。正確さは、Kafka と Flink の1回限りのセマンティクス、Pinot のアップサート (upsert) 操作、およびべき等と重複排除の目的による一意のレコード識別子を活用することで実現される。
Kafka トランザクションと Flink チェックポイントおよびこの 2 フェーズコミットプロトコルの組み合わせにより、Kafka のコンシューマは完全に処理されたイベントのみが表示される。さらに、チェックポイントに格納されている Kafka オフセットがコミットされたレコードと一致していることを示している。Kafka トランザクションは、失敗によって引き起こされたコミットされないイベントはすべて無視される。Flink のチェックポイントは定期的に発生し、障害が発生した場合に既知の適切な時点から状態とストリームの位置を回復できるようにすることで、ステートフルジョブに障害のない実行と同様のセマンティクスを提供する。Flink のチェックポイントを 2 フェーズコミットプロトコルと組み合わせると、正確に1回のセマンティクスが可能になる。
出典: https://eng.uber.com/real-time-exactly-once-ad-event-processing/
入力される生の広告イベントは検証され、Flink のキー設定された状態を使用して重複排除され、Docstore データベースに一時的に保存され、1分間のタンブリングウィンドウに集約される。著者は、この1分間のウィンドウを選択したのは、分析のための適切な粒度を提供するのに十分小さいと同時に、書き込み操作によるデータベースの過負荷を回避するのに十分な大きさであるためだと説明している。集約結果は一意の識別子を受け取る。
別のジョブは、注文と広告イベントを関連付ける。この結果も一意の識別子を受け取る。著者は、Docstore データベースに保存されている広告イベントの存続時間設定により、関連するイベントのみが保持されることが保証されると付け加えている: これらは相関ウィンドウの期間中にだけ存在する。
著者によると、生成された一意のレコード識別子は、Pinot のアップサート機能で使用され、同じ識別子を持つレコードが重複しないようにし、正確に1回のセマンティクスを維持する。これらは、レコードの重複排除のため Hive で同じ目的で使用される。
著者は、Pinot のデプロイメントは、2つのリージョン間でアクティブ-アクティブであり、データを複製しないことを指摘している。したがって、Flink ジョブは両方のリージョンからのイベントを結合し、同じデータが両方に確実に保存されるようにする。
Apache Kafka は、業界で広く使用されている分散イベントストリーミングプラットフォームだ。Apache Flink は、低レイテンシーで、信頼性が高く、正確に1回の特性があるため、ストリーミングデータでステートフル計算を実行するために使用される。Apache Pinot を使用すると、ユーザー向けのレイテンシーに敏感な分析アプリケーションを構築できる。