優步是如何使用Apache Flink和Kafka實現實時Exactly-Once廣告事件處理?

banq發表於2021-09-28

優步最近推出了一項新功能:UberEats 上的廣告。這種新能力帶來了 Uber 需要解決的新挑戰,例如廣告拍賣、競標、歸因、報告等系統。本文重點介紹我們如何利用開源技術構建 Uber 的第一個“近實時”恰好一次事件處理系統。我們將深入瞭解我們如何實現一次性處理以及事件處理作業的內部工作原理的細節。
 
問題陳述:
對於每個投放的廣告,每個使用者都有相應的事件(展示次數、點選次數)。廣告事件處理系廣告系統)。
這需要一個針對以下方面進行最佳化的系統:
  1. 速度:
    1. 下游廣告系統(廣告節奏、預算更新)需要使用者生成的廣告事件的實時上下文才能履行其職責。
    2. 客戶將以最少的延遲看到他們的效能指標。
  2. 可靠性:
    1. 系統在資料完整性方面必須可靠。廣告事件代表支付給優步的實際資金。如果事件丟失,優步就會失去潛在收入。
    2. 我們必須能夠準確地向客戶展示廣告的效果。資料丟失會導致廣告成功率低報,從而導致客戶體驗不佳。
  3. 準確性:[list=1]
  4. 我們不能高估事件。重複計算點選次數,導致向廣告商收取過高費用並高估廣告的成功率。兩者都是糟糕的客戶體驗,這需要處理事件恰好一次
  5. 優步是投放廣告的市場,因此我們的廣告歸因必須 100% 準確。

  

架構
為了滿足這些需求,我們設計了一個嚴重依賴 4 項關鍵開源技術的架構:Apache Flink  、Apache Kafka  、Apache Pinot  和 Apache Hive  。以下是選擇每種技術的原因。

  • 使用 Apache Flink 進行流處理

該系統的核心構建塊使用Apache Flink,這是一種用於近實時處理無界資料的流處理框架。它具有非常適合廣告的豐富功能集,例如一次性保證、Kafka 聯結器(Uber 的選擇訊息佇列)、用於聚合的視窗函式,並且在 Uber 中得到了很好的整合和支援。 
 
  • 使用 Apache Kafka 的訊息佇列

Kafka 是 Uber 技術堆疊的基石:我們擁有世界上最大的 Kafka 部署之一,並且做了大量有趣的工作來確保它的效能和可靠性。Kafka 還可以提供一次性保證,並且可以很好地擴充套件到廣告用例。
 
  • 使用 Apache Pinot 進行實時分析

廣告事件處理系統的主要目標之一是為我們的客戶快速提供效能分析:Apache Pinot 出現了。Pinot 是分散式、可擴充套件的線上分析處理 (OLAP) 資料儲存。它專為分析查詢的低延遲交付而設計,並支援透過 Kafka 進行近實時資料攝取。
 
  • 使用 Apache Hive 的資料倉儲

Apache Hive是一個資料倉儲,它透過允許透過 SQL 查詢資料的豐富工具促進讀取、寫入和管理大型資料集。優步擁有透過 Kafka 的自動化資料攝取流,以及使 Hive 成為儲存資料的絕佳解決方案,供資料科學家用於報告和資料分析的內部工具。

 

恰好一次
如上所述,我們正在處理的一個主要約束是要求在整個系統中使用恰好一次語義。這是分散式系統中最困難的問題之一,但我們能夠透過多種努力來解決它。 
首先,我們依靠 Flink 和 Kafka 中的一次性配置來確保透過 Flink 處理並沉入 Kafka 的任何訊息都是事務性地完成的。Flink 使用啟用了“read_committed”模式的 KafkaConsumer,它只會讀取事務性訊息。作為本部落格中討論的工作的直接結果,Uber 啟用了此功能。其次,我們為聚合作業生成的每條記錄生成唯一識別符號,下面將詳細介紹。識別符號用於下游消費者中的冪等性和重複資料刪除目的。 
第一個 Flink 作業 Aggregation 使用來自 Kafka 的原始事件並按分鐘將它們聚合到桶中。這是透過將訊息的時間戳欄位截斷為一分鐘並將其與廣告識別符號一起用作複合鍵的一部分來完成的。在這一步,我們還為每個聚合結果生成一個隨機唯一識別符號(記錄 UUID)。
每分鐘滾動視窗都會觸發將聚合結果傳送到處於“未提交”狀態的 Kafka 接收器,直到下一個Flink 檢查點觸發。當下一個檢查點觸發時(每 2 分鐘),訊息將使用兩階段提交協議轉換為“已提交”狀態。這確保了儲存在檢查點中的 Kafka 讀取偏移量始終與提交的訊息一致。
Kafka 主題的使用者(例如,廣告預算服務和聯合與載入作業)被配置為僅讀取已提交的事件。這意味著所有可能由 Flink 故障引起的未提交事件都將被忽略。所以當 Flink 恢復時,它會再次重新處理它們,生成新的聚合結果,將它們提交給 Kafka,然後它們可供消費者處理。
記錄 UUID 用作廣告預算服務中的冪等鍵。對於 Hive,它用作重複資料刪除目的的識別符號。在 Pinot 中,我們利用 upsert 功能來確保我們永遠不會複製具有相同識別符號的記錄。
 

總結
在這篇部落格中,我們展示了我們如何利用開源技術(Flink、Kafka、Pinot 和 Hive)來構建滿足快速、可靠和準確系統要求的事件處理系統。我們討論了在分散式系統中確保完全一次語義的一些挑戰,並展示了我們如何透過生成冪等鍵和依賴 Pinot 的最新功能之一來實現這一點:Upsert。在撰寫這篇博文時,該系統每週處理數億個廣告事件,並且每天都在增加。
 

相關文章