[譯] Databook:經過元數據,Uber 將大數據轉化爲知識

從司機與乘客的位置和目的地,到餐館的訂單和支付交易,Uber 的運輸平臺上的每次互動都是由數據驅動的。數據賦能了 Uber 的全球市場,使咱們面向全球乘客、司機和食客的產品得以具有更可靠、更無縫的用戶體驗,並使咱們本身的員工可以更有效地完成工做。html

憑藉系統的複雜性和數據的普遍性,Uber 將數據驅動提高到了一個新的水平:天天處理萬億級的 Kafka 消息,橫跨多個數據中心的 HDFS 中存儲着數百 PB 的數據,並支持每週上百萬的分析查詢。前端

然而大數據自己並不足以造成看法。Uber 規模的數據要想被有效且高效地運用,還須要結合背景信息來作業務決策,這才能造成看法。爲此咱們建立了 Uber 的內部平臺 Databook,該平臺用於展現和管理具體數據集的有關內部位置和全部者的元數據,從而使咱們可以將數據轉化爲知識。mysql

業務(和數據)的指數增加

自 2016 年以來,Uber 的平臺上已增長了多項新業務,包括 Uber EatsUber Freight,以及 Jump Bikes。現在,咱們天天至少完成 1500 萬次行程,每個月活躍有超過 7500 萬乘客。在過去的八年中,Uber 已從一家小型創業公司發展到在全球擁有 18,000 名員工。android

隨着這種增加,數據系統和工程架構的複雜性也增長了。例若有數萬張表分散在多個在役的分析引擎中,包括 HivePrestoVertica。這種分散致使咱們急需瞭解信息的全貌,特別是咱們還在不斷添加新業務和新員工。 2015 年的時候,Uber 開始手動維護一些靜態 HTML 文件來對錶進行索引。ios

隨着公司發展,要更新的表和相關元數據的量也在增加。爲確保咱們的數據分析能跟上,咱們須要一種更加簡便快捷的方式來作更新。在這種規模和增加速度下,有個能發現全部數據集及其相關元數據的強大系統簡直不要太贊:它絕對是讓 Uber 數據能利用起來的必備品。git

圖 1:Databook 是 Uber 的內部平臺,能夠展現和管理數據有關內部位置和全部者的元數據。github

爲使數據集的發現和探索更容易,咱們建立了 Databook。 Databook 平臺管理和展現着 Uber 中豐富的數據集元數據,使咱們員工得以探索、發現和有效利用 Uber 的數據。 Databook 確保數據的背景信息 —— 它的意義、質量等 —— 能被成千上萬試圖分析它的人接觸到。簡而言之,Databook 的元數據幫助 Uber 的工程師、數據科學家和運營團隊將此前只能幹看的原始數據轉變爲可用的知識。sql

經過 Databook,咱們摒棄了手動更新,轉爲使用一種先進的自動化元數據庫來採集各類常常刷新的元數據。Databook 具備如下特性:數據庫

  • 拓展性: 易於添加新的元數據、存儲和記錄。
  • 訪問性: 全部元數據可被服務以程序方式獲取。
  • 擴展性: 支持高通量讀取。
  • 功能性: 跨數據中心讀寫。

Databook 提供了各類各樣的元數據,這些元數據來自 Hive、Vertica、MySQLPostgresCassandra 和其餘幾個內部存儲系統,包括:apache

  • 表模式
  • 表/列的說明
  • 樣本數據
  • 統計數據
  • 上下游關係
  • 表的新鮮度、SLA 和全部者
  • 我的數據分類

全部的元數據均可以經過一箇中心化的 UI 和 RESTful API 來訪問到。 UI 使用戶能夠輕鬆訪問到元數據,而 API 則使 Databook 中的元數據能被 Uber 的其餘服務和用例使用。

雖然說當時已經有了像 LinkedIn 的 WhereHows 這種開源解決方案,但在 Databook 的開發期間,Uber 尚未採用 Play 框架Gradle(譯者注:二者爲 WhereHows 的依賴)。 且 WhereHows 缺少跨數據中心讀寫的支持,而這對知足咱們的性能需求相當重要。所以,利用 Java 自己強大的功能和成熟的生態系統,咱們建立了本身內部的解決方案。

接下來,咱們將向您介紹咱們建立 Databook 的過程以及在此過程當中咱們遇到的挑戰。

Databook 的架構

Databook 的架構能夠分爲三個部分:採集元數據、存儲元數據以及展現元數據。下面圖 2 描繪的是該工具的總體架構:

圖 2:Databook 架構:元數據從 Vertica、Hive 和其餘存儲系統中獲取,存儲到後端數據庫,經過 RESTful API 輸出。

Databook 引入多個數據源做爲輸入,存儲相關元數據並經過 RESTful API 輸出(Databook 的 UI 會使用這些 API)。

在初次設計 Databook 時,咱們就必須作出一個重大的決定,是事先採集元數據存起來,仍是等到要用時現去獲取?咱們的服務須要支持高通量和低延遲的讀取,若是咱們將此需求託付給元數據源,則全部元數據源都得支持高通量和低延遲的讀取,這會帶來複雜性和風險。好比,獲取表模式的 Vertica 查詢一般要處理好幾秒,這並不適合用來作可視化。一樣,咱們的 Hive metastore 管理着全部 Hive 的元數據,令其支持高通量讀取請求會有風險。既然 Databook 支持許多不一樣的元數據源,咱們就決定將元數據存儲在 Databook 自身的架構中。此外,大多數用例雖然須要新鮮的元數據,但並不要求實時看到元數據的更改,所以按期爬取是可行的。

咱們還將請求服務層與數據採集層分開,以使二者能運行在獨立的進程中,以下面的圖 3 所示:

圖 3:Databook 由兩個不一樣的應用層組成:數據採集爬蟲和請求服務層。

兩層隔離開可減小附帶影響。例如,數據採集爬蟲做業可能佔用較多的系統資源,沒隔離就會影響到請求服務層上 API 的 SLA。另外,與 Databook 的請求服務層相比,數據採集層對中斷不太敏感,若是數據採集層掛掉,可確保仍有以前的元數據能提供,從而最大限度地減小對用戶的影響。

事件驅動採集 vs 定時採集

咱們的下一個挑戰是肯定如何最且成效且最高效地從多種不一樣數據源採集元數據。咱們考慮過多種方案,包括建立一個分佈式的容錯框架,利用基於事件的數據流來近乎實時地檢測和調試問題。

咱們先建立了爬蟲來按期採集各類數據源和微服務生成的有關數據集的元數據信息,例如表的使用數據統計,它由咱們用於解析和分析 SQL 的強大開源工具 Queryparser 生成。(順帶一提:Queryparser 也由咱們的「數據知識平臺」團隊建立)。

咱們須要以可擴展的方式頻繁採集元數據信息,還不能阻塞到其餘的爬蟲任務。爲此,咱們將爬蟲部署到了不一樣的機器,這就要求分佈式的爬蟲之間能進行有效協調。咱們考慮配置 Quartz 的集羣模式(由 MySQL 支持)來作分佈式調度。可是,卻又面臨兩個實現上的障礙:首先,在多臺機器上以集羣模式運行 Quartz 須要石英鐘的按期同步,這增長了外部依賴,其次,在啓動調度程序後咱們的 MySQL 鏈接就一直不穩定。最後,咱們排除了運行 Quartz 集羣的方案。

可是,咱們仍然決定使用 Quartz,以利用其強大的內存中調度功能來更輕鬆、更高效地向咱們的任務隊列發佈任務。對於 Databook 的任務隊列,咱們用的是 Uber 的開源任務執行框架 Cherami。這個開源工具讓咱們能在分佈式系統中將消費程序解耦,使其能跨多個消費者羣組進行異步通訊。有了 Cherami,咱們將 Docker 容器中的爬蟲部署到了不一樣的主機和多個數據中心。使用 Cherami 使得從多個不一樣來源採集各類元數據時不會阻塞任何任務,同時讓 CPU 和內存的消耗保持在理想水平並限制在單個主機中。

儘管咱們的爬蟲適用於大多數元數據類型,但有一些元數據還須要近乎實時地獲取,因此咱們決定過渡到基於 Kafka 的事件驅動架構。有了這個,咱們就能及時檢測和調試數據中斷。咱們的系統還能夠捕獲元數據的重大變更,例如數據集上下游關係和新鮮度,以下面的圖 4 所示:

圖 4:在 Databook 中,對每一個表採集上下游關係/新鮮度元數據。

這種架構使咱們的系統可以以程序方式觸發其餘微服務並近乎實時地向數據用戶發送信息。但咱們仍需使用咱們的爬蟲執行諸如採集/刷新樣本數據的任務,以控制對目標資源的請求頻率,而對於在事件發生時不必定須要採集的元數據(好比數據集使用狀況統計)則自動觸發其餘系統。

除了近乎實時地輪詢和採集元數據以外,Databook UI 還從使用者和生產者處採集數據集的說明、語義,例如表和列的描述。

咱們如何存儲元數據

在 Uber,咱們的大多數數據管道都運行在多個集羣中,以實現故障轉移。所以,同一張表的某些類型的元數據的值(好比延遲和使用率)可能因集羣的不一樣而不一樣,這種數據被定義爲集羣相關。相反,從用戶處採集的說明元數據與集羣無關:描述和全部權信息適用於全部集羣中的同一張表。 爲了正確關聯這兩種類型的元數據,例如將列描述與全部集羣中的表列相關聯,能夠採用兩種方案:寫時關聯或讀時關聯。

寫時關聯

將集羣相關的元數據與集羣無關的元數據相關聯時,最直接的策略是在寫入期間將元數據關聯在一塊兒。例如,當用戶給某個表列添加描述時,咱們就將信息保存到全部集羣的表中,以下面的圖 5 所示:

圖 5:Databook 將集羣無關的元數據持久化保存到全部表中。

這方案可確保持久化數據保持整潔。例如在圖 5 中,若是「列 1」不存在,該集羣就會拒絕該請求。但這存在一個重要的問題:在寫入時將集羣無關的元數據關聯到集羣相關的元數據,全部集羣相關的元數據必須已經存在,這在時間上只有一次機會。例如,當在圖 5 中改動表列描述時,還只有集羣 1 有此「列 1」,則集羣 2 的寫入失敗。以後,集羣 2 中同一個表的模式被更新,但已錯失機會,除非咱們按期重試寫入,不然此描述將永遠不可用,這致使系統複雜化。下面圖 6 描述了這種狀況:

圖 6:Databook 將集羣無關的元數據持久保存到全部表中。

讀時關聯

實現目標的另外一種方案是在讀取時關聯集羣無關和集羣相關的元數據。因爲這兩種元數據是在讀取時嘗試關聯,無所謂集羣相關的元數據一時是否存在,所以這方案能解決寫時關聯中丟失元數據的問題。當表模式更新後顯示「列 1」時,其描述將在用戶讀取時被合併,以下面圖 7 所示:

圖 7:Databook 在讀取時關聯集羣相關和集羣無關的元數據。

存儲選擇

Databook 後端最初是使用 MySQL,由於它開發速度快,能夠經過 Uber 的基礎設施自動配置。可是,當涉及多數據中心支持時,共享 MySQL 集羣並不理想,緣由有三:

  • 單個主節點:首先,Uber 僅支持單個主節點,致使其餘數據中心的寫入時間較慢(咱們這狀況每次寫入增長約 70ms)。
  • 手動提權:其次,當時不支持自動提權。所以,若是主節點掛掉,要花數小時才能提高一個新的主節點。
  • 數據量:咱們棄用 MySQL 的另外一個緣由是 Uber 所產生的大量數據。咱們打算保留全部歷史變動,並但願咱們的系統支持將來擴展,而無需在集羣維護上花費太多時間。

出於這些緣由,咱們選擇 Cassandra 來取代 MySQL,由於它具備強大的 XDC 複製支持,容許咱們從多個數據中心寫入數據而不會增長延遲。並且因爲 Cassandra 具備線性可擴展性,咱們再也不須要擔憂適應 Uber 不斷增加的數據量。

咱們如何展現數據

Databook 提供了兩種訪問元數據的主要方法:RESTful API 和可視化 UI。Databook 的 RESTful API 用 Dropwizard(一個用於高性能 RESTful Web 服務的 Java 框架)開發,並部署在多臺計算機上,由 Uber 的內部請求轉發服務作負載平衡。

在 Uber,Databook 主要用於其餘服務以程序方式訪問數據。例如,咱們的內部查詢解析/重寫服務依賴於 Databook 中的表模式信息。API 能夠支持高通量讀取,而且能夠水平擴展,當前的每秒查詢峯值約爲 1,500。可視化 UI 由 React.js 和 Redux 以及 D3.js 編寫,主要服務於整個公司的工程師、數據科學家、數據分析師和運營團隊,用以分流數據質量問題並識別和探索相關數據集。

搜索

搜索是 Databook UI 的一項重要功能,它使用戶可以輕鬆訪問和導航表元數據。咱們使用 Elasticsearch 做爲咱們的全索引搜索引擎,它從 Cassandra 同步數據。以下面圖 8 所示,使用 Databook,用戶可結合多個維度搜索,例如名稱、全部者、列和嵌套列,從而實現更及時、更準確的數據分析:

圖 8:Databook 容許用戶按不一樣的維度進行搜索,包括名稱、全部者和列。

Databook 的新篇章

經過 Databook,Uber 如今的元數據比以往更具可操做性和實用性,但咱們仍在努力經過建造新的、更強大的功能來擴展咱們的影響力。咱們但願爲 Databook 開發的一些功能包括利用機器學習模型生成數據看法的能力,以及建立高級的問題檢測、預防和緩解機制。

若是結合內部和開源解決方案創建可擴展的智能服務並開發有創意的複雜技術對您來講有吸引力,請聯繫 Zoe Abrams(za@uber.com)或申請咱們團隊的職位

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索