Uber實時資料基礎設施:分散式計算架構
Uber 的實時資料基礎設施:
- Apache Kafka 用於流式儲存,
- Flink 用於流處理,
- Pinot 用於 OLAP,
- HDFS 用於歸檔儲存,
- Presto 用於互動式查詢
資料來源與挑戰
Uber 生成的主要資料來源是其資料中心內的終端使用者應用程式,例如 Uber(拼車)和 UberEats。這些資料包括客戶端事件和來自優步應用程式中執行的微服務的系統日誌。實時資料的生成還來自生產資料庫的變更日誌,其中正在處理實時事務。對這些資料進行處理以涵蓋可以在這三個類別中較高階別涵蓋的大量使用。
- 訊息平臺
- 流處理
- 線上分析處理
構建滿足上述用例的資料基礎架構所帶來的主要挑戰是:
- 隨著使用者群的增加,正在生成的資料呈指數增長。同樣出於永續性和可用性的目的,資料來源可以部署在多個位置。資料基礎設施需要確保資料的新鮮度並以最小的延遲提供對這些資料的訪問。
- 資料基礎設施應該是可擴充套件的,以適應未來的用例,這些用例可以像多階段機器學習模型到簡單的 SQL 查詢介面一樣複雜。
- 隨著希望訪問和處理資料的使用者數量的增加,資料基礎設施應該是可擴充套件的。它還應該為廣泛的使用者提供工具。因此,能夠在 Python 中部署 ML 模型的工程師應該沒有問題,而想要查詢專案實時財務的財務背景的員工應該能夠透過使用類似 SQL 的簡單介面來實現它。
資料基礎設施的期望是滿足廣泛的用例,並抽象出捕獲和維護來自多個來源的實時資料所涉及的複雜性。
資料基礎設施要求
由於資料基礎設施必須解決各種各樣的用例,因此縮小所有用例中常見的要求非常重要。在所有用例中找到共同點的需求列表如下:
- 資料需要跨地區保持一致,因為最終用例可能位於無法容忍資料不一致的金融等關鍵領域。
- 系統需要高度可用,因為許多實時決策會影響日常運營。動態定價模型依賴於使用來自基礎設施的實時資料,並直接影響向客戶收取的優步乘車價格。
- 資料需要是新鮮的,或者換句話說,它應該在生成後的幾秒鐘內可用。這也會影響 Uber 系統做出正確決策的能力,如果這些決策是透過處理陳舊資料做出的,則會導致業務損失或客戶體驗不佳。
- 查詢消耗的資料對延遲非常敏感。查詢的高延遲將直接影響終端使用者的體驗。
- 資料基礎設施應該隨著 Uber 客戶群的增長而擴充套件。
- 由於優步是一個低利潤的企業,資料基礎設施的成本應該儘可能低。
- 資料基礎設施需要為各種各樣的使用者提供服務,因此它應該公開查詢和可程式設計介面。
有了這麼多的用例,不可能在 Uber 的規模上提供高度一致的資料以及可用性。因此,實時基礎設施有利於資料的新鮮度而不是資料的一致性。
抽象
資料基礎架構帶有一組從儲存層一直到查詢層的抽象。這些抽象的高階概述如下所示:
讓我們嘗試一次剖析上述抽象中呈現的元件,從儲存(從終端使用者到 API 和 SQL 的最抽象的元件)到使用者直接與資料基礎設施互動的 API 和 SQL 的頂層。
- 儲存:儲存以通用物件或 blob 格式儲存資料。它主要是為寫入繁重的用例而不是讀取用例而構建的,因為它的作用主要是圍繞資料的長期儲存。OLAP 或流元件直接從儲存中讀取,以呈現上游用例的資料。
- 流:這為客戶端提供了釋出者-訂閱者介面。客戶端可以訂閱一個或多個主題並一次使用一個事件。該元件的首要目標是對資料進行分割槽併為已釋出的事件提供至少一種語義。
- Compute:它負責對來自流或直接來自儲存的事件執行操作。可以使用各種技術來執行這些計算,並且可以使用相同/不同的技術來計算流/儲存資料。
- OLAP:這為來自流或儲存的資料提供了有限的 SQL 介面。它針對分析查詢進行了最佳化。
- SQL:該元件在 OLAP 和計算之上提供了一個成熟的 SQL 介面。在計算之上工作時,SQL 函式被轉換為編譯函式,並應用於流或儲存之上。與 OLAP 互動時,它在 OLAP 查詢之上提供附加功能,例如 JOINS。
- API:該元件為 SQL 介面無法實現的更復雜用例提供可程式設計介面。
- 後設資料:該元件為管理系統中上述元件的後設資料提供支援。
系統總覽
最初我們討論了 Uber 使用多種開源技術來構建他們的資料基礎設施。它透過針對我們討論的用例調整它們來做到這一點,並改進它們以填補空白。作為概述的一部分,我們將一一研究這些技術,以瞭解它們如何幫助 Uber 構建強大的資料基礎設施。
用於流式儲存的 Apache Kafka
Kafka是一個著名的開源事件流系統,Uber 目前管理著業內最大的 Kafka 叢集之一來構建他們的資料基礎設施。在 Uber,Kafka 負責將流資料傳輸到批處理和實時處理系統。使用案例的範圍可以從將事件從駕駛員/騎手應用程式傳送到底層分析平臺,再到流式資料庫更改日誌,再到基於這些事件執行計算的訂閱者。考慮到各種用例和可擴充套件性要求,Uber 定製了 Kafka 並新增了一些改進,例如:
- 叢集聯合: Uber 開發了一種對叢集的抽象,它向生產者/消費者隱藏了叢集的內部細節。它是透過向使用者公開一個邏輯叢集而不是原始叢集來完成的。叢集聯合負責管理與叢集相關的後設資料並將使用者的請求路由到正確的物理叢集。這有助於在叢集故障期間,因為使用者現在不關心他們需要連線到哪個物理叢集並更新與其關聯的後設資料。這反過來又提高了系統的可用性,也透過消除使用者過多的叢集管理工作量並讓他們專注於核心業務邏輯來提高系統的可擴充套件性。
- 死信佇列:在Kafka中,沒有被下游客戶端處理的訊息要麼被要求丟棄(導致資料丟失)要麼需要無限期重試(進而影響系統效能並阻塞佇列)。這兩種方法最終都可能成為資料基礎架構中的瓶頸,既不想永久丟失資料,又不想阻止其他訊息得到處理。優步透過建立一個死信佇列來解決這個問題,在該佇列中,在某組重試之後沒有被消費的訊息被推送到該佇列,進而清除佇列以處理其他訊息。這些訊息與死信主題相關聯,使用者可以根據自己的要求決定稍後處理它們或永久刪除它們。
- 消費者代理:這是對 Kafka 提供的消費者客戶端庫執行出色封裝的另一個示例。由於 Uber 有大量客戶端使用來自 Kafka 的訊息,因此很難為所有客戶端提供更新版本的客戶端庫。各種程式語言的使用增加了這一挑戰。為了克服這個問題,Uber 在來自 Kafka 的客戶端庫和作為gRPC服務託管的使用者訊息處理邏輯之間建立了一個層。此抽象還透過將訊息移動到死信佇列來執行錯誤處理,因為使用者的服務在一組重試後無法使用它。
- 跨叢集複製:由於需要跨區域複製資料以實現容錯,這需要跨多個資料中心的Kafka叢集複製資料。為了實現這一點,Uber 開發了一個開源複製器,用於在 Kafka 叢集之間複製訊息,稱為uReplicator。為了驗證跨叢集複製沒有資料丟失,Uber 還開發了Chaperone,它充當 Kafka 審計系統,並在檢測到資料不匹配時發出警報。
透過上述改進,Uber 能夠在 Apache Kafka 之上構建一個可擴充套件且容錯的訊息傳遞平臺。
用於流處理的 Apache Flink
為了處理來自 Kafka 的實時資料,Uber 使用構建在Apache Flink之上的流處理系統,這是一個開源流處理框架。Flink 用於面向使用者的產品和內部分析。它透過 SQL 介面和可程式設計 API 向使用者公開,用於執行更復雜的工作負載。為了針對 Uber 的用例調整 Flink,在框架之上新增了某些改進。
- 使用 SQL 構建流分析應用程式: Uber 在 Flink 之上建立了一個名為 FlinkSQL 的 SQL 介面,並將其作為開源專案的一部分。FlinkSQL 讓非程式設計背景的使用者只需編寫 SQL 查詢即可輕鬆使用流處理。這個介面是一個很好的抽象,它隱藏了使用 Flink 框架的低階 API、作業管理和資源估計的複雜性。現在使用者可以專注於他們的業務邏輯,其餘的由框架處理。許多工程努力都落後於解決這種抽象帶來的挑戰。這些挑戰中很少有:
- 資源估計和自動縮放
- 作業監控和故障自動恢復
- 部署、管理和操作的統一架構:由於使用者由 SQL 和 API 介面提供,因此這兩種操作都有一定的功能集。平臺層用於在核心 API 之上提供更豐富的功能,它負責將業務邏輯轉換為核心 Flink 作業定義,並將其傳送到作業管理層進行進一步處理。作業管理層執行作業的驗證並管理從部署到監控和故障恢復的整個作業生命週期。儲存層託管儲存後端和計算叢集。
透過這些改進,Flink 已成為 Uber 的核心流處理框架。隨著這些改進傳遞到開源框架,它也使 Flink 社群受益。
用於 OLAP 的 Apache Pinot
Apache Pinot是一個開源的分散式 OLAP 系統,可以對大規模資料執行低延遲查詢。它採用分散-收集-合併方法,將大型資料集拆分為段,將查詢分解為子計劃並並行執行,然後合併結果。 優步將 Pinot 用於各種分析用例,例如實時乘車供需指標和 UberEats 訂單統計。它還用於透過為實時資料提供可操作的結果來為許多後端伺服器中的決策制定提供動力。優步為 Pinot 做出了貢獻,以增強其處理優步獨特需求的能力。
- Upsert 支援: Upsert是單詞更新和插入的組合。在資料庫世界中,如果指定的值存在,則 upsert 操作將更新現有記錄,如果值不存在,則插入新記錄。在 Uber,upsert 操作用於更新 UberEats 訂單的交付狀態或在各種情況下更正乘車費用,例如當乘客更新他們的下車地點時。Uber 在 Apache Pinot 中設計和開發了 upsert 功能,使其成為唯一支援 upsert 功能的開源 OLAP 商店之一。
- 完整的 SQL 支援:開源 Pinot 版本不支援豐富的 SQL 功能,例如子查詢和連線。為了克服這一挑戰,Uber 將 Pinot 與Presto(分散式查詢引擎)整合在一起,使使用者能夠在 Pinot 之上使用標準 PrestoSQL 查詢。
- 與資料生態系統的其他部分整合:Pinot 已與 Uber 資料基礎設施的其他元件整合,以提供無縫的開發人員體驗。此類整合的一些示例包括:
- 與 Uber 模式服務整合以從 Kafka 主題中自動推斷模式
- 與 FlinkSQL 整合作為資料接收器,允許使用者執行 SQL 轉換並將結果推送到 Pinot
- 對等分段恢復:最初,Pinot 嚴格依賴外部資料儲存進行歸檔,以便從任何型別的故障中恢復。如果檔案商店出現故障並反過來完全停止檔案過程,這很快就會成為瓶頸。優步透過用非同步解決方案替換原始設計來解決這個問題,其中伺服器副本可以在故障期間為存檔段提供服務。集中式段儲存現在被點對點方案取代,從而提高了攝取過程的可靠性和容錯性。
再加上上述改進,Apache Pinot 已被 Uber 的資料生態系統廣泛採用。與此同時,優步不斷投資以改進 Pinot,以更好地應對即將到來的挑戰。
用於歸檔儲存的 HDFS
Uber 使用HDFS為其資料基礎設施長期儲存資料。來自 Kafka 的資料採用 Avro 格式,並作為日誌儲存在 HDFS 中。這些日誌合併為 Parquet 格式,並使用 Hive、Presto 或 Spark 等框架進行處理。這些資料集被視為資料基礎架構中的真實來源,並被各種系統用於回填目的。HDFS 還被多個其他系統用於滿足其儲存需求。
Presto 互動式查詢 Presto 是 Facebook 開發的開源、分散式和互動式查詢引擎。Presto 的設計目標是對大規模資料進行快速分析查詢,並且從某種意義上說它非常靈活,可以很容易地與各種資料來源整合。正如我們針對 Pinot 所討論的,Presto 被資料科學家和工程師透過與 Pinot 整合來對新資料進行探索性分析。
學過的知識
擁有強大且可擴充套件的資料基礎架構為透過探索資料提出新想法並以更好的方式幫助客戶提供了可能性。本文中描述的一個此類示例是“UberEats 餐廳經理”的儀表板。該儀表板向餐廳老闆提供有關實時客戶滿意度、熱門訂單專案等的實時檢視,這可以幫助他們實時做出業務決策。擁有這樣的儀表板需要訪問具有快速查詢能力的更新資料,而精心設計的資料基礎架構可以滿足這一要求。 除了構建滿足上述有趣用例的資料架構外,開發過程還伴隨著一組可在設計此類基礎架構期間使用的學習。其中一些學習是:
- 開源採用: Uber 的大部分資料基礎設施都建立在多種開源技術之上。雖然這確實提供了堅實的基礎,但它也伴隨著一系列挑戰。最大的挑戰是大多數開源產品都是為以最佳方式解決特定問題而構建的。而在 Uber,資料基礎設施需要解決大量的用例列表,並且可以為未來的用例擴充套件。這需要 Uber 付出大量的努力,透過投入大量的工程工作來調整和修改這些解決方案以適應他們的用例。其中一個例子是在 Apache Flink 專案之上構建一個完整的 SQL 層。
- 快速的系統開發和演進:以 Uber 的規模構建資料基礎設施需要很多活動。業務需求可能會迅速變化,可能會新增新的需求,並且需要及時納入新的法規和合規性要求。這需要一個摩擦最小的開發工作流程。Uber 透過標準化客戶端介面來實現這一點,這樣未來的介面就不會最終破壞客戶端程式碼。瘦客戶端也是優步用來高效執行客戶端升級的一種非常有效的解決方案。一個例子是構建一個 RESTful Kafka 客戶端,其他服務使用它而不是直接使用原始 Kafka 客戶端。標準化和適當的抽象有助於 Uber 加快開發人員的工作流程,這有助於應對需求的突然變化。
- 易於操作和監控:優步在自動化系統部署方面投入了大量資金。他們將這種自動化與對基礎設施的各種元件的實時監控相結合,每當檢測到系統中的任何差異時都會發出警報。
- 易於使用者入職和除錯:隨著資料基礎設施的使用規模,有必要為使用者提供正確的工具集,用於入職和除錯典型的工作流特定問題。資料發現和資料審計等技術允許使用者發現他們正在尋找的資料,並在公司範圍內檢測資料問題。每當新服務上線時,基礎設施也會自動配置 Kafka 主題,並隨著使用量的增加配置資源。這為使用者提供了無縫的入職體驗,因此他們可以專注於他們的用例,而不是弄清楚基礎設施的複雜性。
我們已經看到在構建強大且可擴充套件的資料基礎架構以支援 Uber 規模的組織的資料需求方面付出了多少努力。這些工作包括瞭解需求及其擴充套件的範圍、利用開源工具使您無需從頭開始構建每個元件、針對您的用例修改這些工具以及建立一個生態系統,您的使用者可以利用該生態系統構建資料解決方案來解決問題複雜的業務問題。
相關文章
- IT架構的基礎實施架構
- 剖析ElasticSearch基礎分散式架構Elasticsearch分散式架構
- 基於Hadoop的大資料平臺實施——整體架構設計Hadoop大資料架構
- 金融級分散式資料庫架構設計要點分散式資料庫架構
- 《圖解雲端計算架構:基礎設施和API》中的網址圖解架構API
- 架構設計 | 分散式事務①概念簡介和基礎理論架構分散式
- Uber如何安全保護Kafka基礎設施?Kafka
- (一) MdbCluster分散式記憶體資料庫——基礎架構介紹分散式記憶體資料庫架構
- 分散式架構基礎:Java RMI詳解分散式架構Java
- 架構設計之一——基礎架構架構
- 商業銀行基於容器雲的分散式資料庫架構設計與創新實踐分散式資料庫架構
- 分散式發號器架構設計分散式架構
- 分散式|Dubbo架構設計詳解分散式架構
- 架構設計基礎:單服務.叢集.分散式,基本區別和聯絡架構分散式
- 美團即時物流的分散式系統架構設計分散式架構
- 從0到10億,微信後臺架構及基礎設施設計與實踐!架構
- 多利熊基於分散式架構實踐穩定性建設分散式架構
- 如何設計一個微型分散式架構?分散式架構
- python分散式爬蟲如何設計架構?Python分散式爬蟲架構
- 分散式時序資料庫QTSDB的設計與實現分散式資料庫QT
- 雲端計算時代,資料庫架構設計有哪些改變?資料庫架構
- 基於SpringCloud分散式架構SpringGCCloud分散式架構
- Grail:Uber是如何管理大規模基礎設施的AI
- 個人伺服器基礎設施架構簡介伺服器架構
- 基於函式計算的 BFF 架構函式架構
- DataPipeline與TiDB推出異構資料實時同步解決方案,共築安全可信基礎設施APITiDB
- 分散式架構篇 | 如何在分散式架構下完美實現“全域性資料一致性”?分散式架構
- Confidential Containers:雲原生機密計算基礎設施IDEAI
- [爬蟲架構] 如何設計一個分散式爬蟲架構爬蟲架構分散式
- (十七)spring cloud微服務分散式雲架構-eureka 基礎SpringCloud微服務分散式架構
- SpringCloud Alibaba實戰(3:儲存設計與基礎架構設計)SpringGCCloud架構
- [分散式]架構設計原則--高併發分散式架構
- 基礎架構設計時,需考慮到哪些內容?架構
- 分散式資料庫架構原理 - Alex Petrov分散式資料庫架構
- Netflix萬億級實時資料基礎設施的四個創新階段
- 基於 dubbo 的分散式架構分散式架構
- 即時基礎設施:以業務速度發展的基礎設施
- (二) MdbCluster分散式記憶體資料庫——分散式架構1分散式記憶體資料庫架構