本文最初發布於 Uber 工程博客,由 InfoQ 中文站翻譯並分享。
前言
數據對於我們的產品而言至關重要。數據分析幫助我們為使用我們服務的用戶提供了流暢的體驗。它也讓工程師、產品經理、數據分析師、數據科學家可以在了解情況後作出明智的決定。數據分析影響了 App 的每一個界面:在主界面上顯示什麼,產品以什麼順序顯示,向用戶顯示哪些相關的信息,什麼妨礙了用戶乘車或註冊,諸如此類。
如此大的用戶群體,如此廣泛的特性,還要覆蓋所有的地理區域,這是一個很複雜的問題。而且,我們的 App 一直在推出新產品,這就要求底層的技術也要有足夠的靈活性來支持這種發展。
數據是實現這種發展的最基本工具。本文將聚焦乘客數據:我們如何收集和處理以及這些數據具體如何影響了乘客端 App 的改進。
乘客數據
乘客數據包含了乘客與 Uber 乘客端 App 的所有交互。其中每天都會有來自 Uber 在線系統的數十億個事件,這些事件轉換成了數百張 Apache Hive 表,為乘客端 App 的不同應用場景提供支持。
下面是可以利用乘客數據分析的主要問題領域:
- 增加漏斗轉化
- 提高用戶參與度
- 個性化
- 用戶溝通
在線數據收集
移動事件日誌
乘客數據有多個來源,但最基本的一個是獲取用戶與 App 的交互過程。用戶交互是通過移動端的事件日誌獲取的。下面是日誌架構設計的一些關鍵原則:
- 日誌標準化
- 跨平台一致性(iOS、Android、Web)
- 尊重用戶隱私設置
- 優化網絡使用
- 可靠但不降低用戶體驗
日誌標準化
有一個標準的日誌記錄過程很重要,因為數以百計的工程師在增加或編輯事件。從客戶端收集的日誌有的是平台化的(像用戶與 UI 元素的交互事件、內容曝光次數等),有的是由開發人員手動添加的。
我們將一組元數據進行了標準化,作為默認的公共負載隨每個事件發送,如位置、App 版本、設備、暱稱等。這對於後台指標計算至關重要。
此外,為了確保所有事件跨所有平台都能保持一致,並且有標準的元數據,我們定義了 Thrift 結構,事件模型需要實現這個結構來定義其有效負載。Thrift 模式包含一個枚舉(表示在不同平台上的事件 ID)和一個有效負載結構(定義了事件註冊時與之關聯的所有數據),最後還有一個事件類型。
示例:Thrift 模式中分析事件的標準化定義
發布日誌
這些日誌通過管道進入 Unified Reporter,這是客戶端里的一個框架,用於攝取客戶端產生的所有消息。Unified Reporter 會將消息存儲在隊列中,對它們進行聚合,然後通過網絡每隔幾秒分批次地發送給後台的 Event Processor。
圖 1 事件被記錄到儀錶盤和數據集的過程
事件一直在增加或變化——每天處理的事件有幾百種類型。其他日益嚴重的問題還有:跨不同作業系統(Android 和 iOS)的日誌平台化、可發現性以及如何保持良好的信噪比。Event Manager 門戶負責管理這些事件的元數據,並為事件選擇合適的接收器。
Event Processor 根據接收到的元數據確定如何處理事件以及進一步傳播。此外,如果事件的元數據和映射不可用,Event Processor 就會阻擋該事件,不再向下游傳播。這是為了提升信噪比。
後台事件日誌
伴隨用戶交互,我們要記錄 App 向用戶展示了什麼內容,這很重要。我們是通過在後台記錄服務層的數據來實現的。後台日誌記錄處理的數據更多,有些是移動端沒有的,有些是移動端處理不過來的。由移動端或其他系統發起的每次後端調用都會有數據記錄。每條記錄都有一個」join「鍵,通過它可以關聯到移動端交互。這項設計可以保證移動端帶寬得到有效使用。
離線數據處理
我們把從移動端和服務層收集到的數據進行結構化,並作為離線數據集進行複製。離線數據集幫助我們識別上文提到的問題,並評估為解決這些問題所開發的解決方案有多成功。
原始的大型離線數據集真得很難處理。我們對原始數據進行擴充並建模,形成分層表。在擴充過程中,我們把不同的數據集連接在一起,讓數據更有意義。建模形成的表可以帶來以下幾個方面的好處:
- 節省資源:僅計算一次並存儲。其他任何人都不需要在原始的大型數據集上運行查詢。
- 標準化定義:業務邏輯和指標定義都在 ETL 中(提取、轉化、加載),不需要消費者操心。如果把這項工作留給消費者,那麼每個團隊可能會做不同的計算。
- 數據質量:可以保證適當的檢查對比,因為邏輯都在一個地方,數據很容易檢驗。
- 所有權:隨著數據演化,數據所有者可以確保表能夠適用於新特性。
圖 2 各種離線數據處理場景
讓我們考慮一下下面這個問題描述:
- 快捷乘車改善了乘客體驗,促成了更多轉化(出行)嗎?
我們從保存了用戶交互和主界面內容的基礎事實表中篩選出與「快捷乘車」相關的信息,並通過與其他多個數據集集成對它進行擴充,進而實現漏斗分析:
- 有多少用戶顯示了快捷乘車區域?
- 有多少用戶點擊了其中的一個快捷方式?
- 有多少用戶(來自 #2)最終預定了出行?
- 有多少用戶(來自 #3)完成了出行?
- 通過快捷乘車流程和普通流程完成出行的主界面曝光比是多少?
- 快捷乘車對於出行預定的總體效果是什麼?
2. 獎勵計劃對於乘客的作用有多大?
為了找出這個問題的答案,表中應該包含如下數據:
- 選擇/兌換的獎勵
- 未使用或過期的獎勵
- 乘客如何贏得獎勵?
還有其他一些有趣的數據點,如:
- 獎勵計劃增加了 App 的總體使用量嗎?
- 支出是否與這項計劃的預算相符?
獎勵可以通過 Eats、Rides 和其他 Uber 應用的不同功能進行兌換。一旦用戶在移動端選擇了一項獎勵,就會觸發中心化的獎勵後端服務。它會處理獎勵信息,將每個獎勵選擇行為記錄為交易數據。有些獎勵是自動應用的,但有些是促銷驅動的。促銷驅動的獎勵兌換是在另一個促銷系統中處理的。此外,這個系統的構建讓運營或產品團隊能夠根據需要輕鬆添加新的獎勵。我們構建工具來獲取獎勵元數據,這些元數據反過來又流向另一個系統。有個 ETL 作業會讀取流經不同系統的數據,生成一個獎勵兌換數據模型。此外,這些數據還能幫助財務團隊獲取 Uber 在獎勵計劃中的開銷,讓人們對這個產品有一個良好的理解。
3. 在 COVID-19 之後,Uber 航空出行的恢復率是多少?
- 航空出行的不同指標是從上游多個表收集的,包括出行、會議、理財、航空出行及其他乘客表等不同的領域。來自不同領域的數據會被聚合,然後在一組維度下計算成指標,存儲到一個表中。將最新數據與經過聚合的歷史數據進行比較,可以幫助我們找到上面這個問題的答案。
- 此外,航空出行數據還被用於繪製機場接機的落地數據熱圖,計算機場總接機量、總預定量等。所有這些數據都有助於我們業務的發展,還有助於業務本地化,滿足不同地域的不同需求。
數據質量
數據可以為我們提供業務決策的依據。因此,保證數據的完整性和質量變得非常重要。在乘客端 App 的架構中,為了保證數據質量,我們在多個層面做了數項檢查。
在產生事件的時候,我們引入了測試框架進行構建時測試、模式和語義檢查。這些框架會檢查是否有分析事件被觸發,有效負載、順序是否符合預期。
圖 3 數據流數據質量檢查
一旦事件到達離線存儲並處理,異常檢測功能就可以保證數據被記錄並按照預期流轉。系統會監控事件量,如果突然出現下降或峰值,就給所有者發送告警信息。這種監控有助於捕捉差異,防止出現中斷而沒有發現。在離線建模的表中,測試框架被用於確保數據的正確性、覆蓋率以及各表之間的一致性。每次管道運行都會觸發配置好的測試,保證產生的任何數據都能滿足質量 SLA(服務水平協議)。
Uber 乘客端 App 的演進
根據上面這些從數據收集機制中了解到的東西,我們對乘客端 App 做了一些更改,下面是幾個具體的例子:
並非所有特性在所有市場中都可用
高質量的數據是推動應用程式演進的強大工具。不說別的,它可以幫助我們改善用戶體驗,這反過來又增加了用戶粘度,促進了用戶增長。此外,在添加新特性的時候,數據可以告訴我們什麼最適合用戶,保證更改不會導致用戶體驗下降。我們深刻理解數據的重要性,我們一直在提升Uber的數據文化。
查看英文原文:How Data Shapes the Uber Rider App