單機每秒最多可處理10億條資料!eBay開源資料處理框架Accelerator

AI前線發表於2018-05-02

單機每秒最多可處理10億條資料!eBay開源資料處理框架Accelerator

策劃編輯 | Natalie
編譯 | 無明
編輯 | Emily
AI 前線導讀:近日,eBay 宣佈正式開源 Accelerator,一款久經考驗的資料處理框架,提供快速的資料訪問,並行執行以及自動組織原始碼、輸入資料和結果。它可以用於日常資料分析,也可以用在包含數十萬大型資料檔案的實時推薦系統上。

Accelerator 可執行在膝上型電腦或機架式伺服器上,輕鬆處理數十億行資料,井然有序地處理成千上萬的輸入檔案、計算和結果。

Accelerator 的資料吞吐量通常在每秒數百萬行。如果執行在高速計算機上,每秒最多可處理幾十億行資料。

更多幹貨內容請關注微信公眾號“AI 前線”,(ID:ai-front)

Accelerator 最初由瑞典人工智慧公司 Expertmaker 開發,於 2012 年正式釋出,從那以後,它一直是眾多研究專案和實時推薦系統的核心工具。 2016 年,Expertmaker 被 eBay 收購,而 eBay 目前正在基於 Apache 許可協議第 2 版開源 Expertmaker Accelerator。

設計目標

Accelerator 的主要設計目標如下:

  • 簡化在多個 CPU 上並行處理資料。

  • 資料吞吐量應儘可能快,即使一臺小型膝上型電腦也能輕鬆處理數百萬行資料。

  • 如果可能,儘量重用計算結果,而不是重新計算。同樣,在多個使用者之間共享結果應該是毫不費力的。

  • 資料科學專案可能會有很多(數十萬)輸入檔案和大量的原始碼和中間結果。

  • Accelerator 應該避免手動管理和記錄資料檔案、計算、結果以及它們之間的關係。

主要功能

Accelerator 主要的原子操作是建立作業。 建立作業是用輸入資料和引數執行一些程式並將結果(即輸出)以及計算所需的所有資訊儲存到磁碟上的過程。 作業目錄將包含計算結果和計算結果所需的所有資訊。

作業可以是簡單或複雜的計算,也可以是大型資料集的容器。 作業之間可以彼此連結,新作業可以依賴於一個或多箇舊作業。

關鍵特性

Accelerator 提供了兩個關鍵功能,結果重用和資料流。

結果重用

在建立新作業之前,Accelerator 會檢查之前是否已經跑過相同的作業。如果已經存在,Accelerator 不會建立這個作業,而是將現有作業的連結返回。這樣不僅節省了執行時間,而且有助於在使用者之間共享結果。更重要的是,它提供了可見性和確定性。

Accelerator 提供了一種機制,將會話中的作業資訊儲存到資料庫中,這樣有助於管理作業和它們相互之間的關係。

資料流

將連續的資料流從磁碟傳輸到 CPU 比在資料庫中執行隨機查詢效率更高。流式傳輸是實現從磁碟到 CPU 高頻寬的最佳途徑。它不需要快取,可以很好地利用作業系統的基於 RAM 的磁碟緩衝區。

整體架構

現在讓我們來看看 Accelerator 的整體架構。

單機每秒最多可處理10億條資料!eBay開源資料處理框架Accelerator

是一個基於客戶端 / 伺服器的應用程式。在左側有一個 runner 客戶端,在右邊有兩臺伺服器,稱為 daemon 和 urd,其中 urd 是可選的。runner 通過執行指令碼(構建指令碼)在 daemon 伺服器上啟動作業。此伺服器將載入和儲存使用基於 workdirs 檔案系統的資料庫執行的所有作業的資訊和結果。同時,構建指令碼中所有有關作業的資訊將由 urd 伺服器儲存到作業日誌檔案系統的資料庫中。 urd 負責管理作業,包括儲存和檢索之前執行過的相關作業的會話或清單。

作業

作業是通過執行稱為 method 的小程式來建立的。method 用 Python 2 或 Python 3 編寫,有時也用 C 語言。

最簡單的作業:“Hello, World”

我們通過一個簡單的“Hello World”程式來說明如何建立一個作業(method):

def synthesis():
  return "hello world"複製程式碼

這個程式不需要任何輸入引數,只是返回一個字串並退出。要執行它,我們還需要建立一個構建指令碼,如下所示:

def main(urd):
  jid = urd.build('hello_world')複製程式碼

當執行完這個方法之後,使用者會得到一個叫作 jobid 的連結。jobid 指向儲存執行結果的目錄,以及執行作業所需的所有資訊。

如果我們嘗試再次執行這個作業,它將不會被執行,而是返回指向上一次執行作業的 jobid,因為 Accelerator 記得之前已經執行過與此類似的作業。 要再次執行作業,我們必須更改原始碼或輸入引數。

連結作業

我們假設剛剛建立的 hello_world 作業非常耗費計算資源,並已經返回了我們想要的結果。為了簡單起見,我們通過建立一個名為 print_result 的方法來演示其中的原理,該方法只讀取前一個作業的結果並將結果列印到 stdout。

import blob

jobids = ('hello_world_job',)

def synthesis(): 
  x = blob.load(jobid=jobids.hello_world_job)
  print(x)複製程式碼

要建立這個作業,我們需要擴充套件構建指令碼:

def main(urd):
  jid = urd.build('hello_world') 
  urd.build('print_result', jobids=dict(hello_world_job=jid))複製程式碼

在執行構建指令碼時,只會建立 print_result 作業,因為 hello_world 作業之前已經建立過了。

作業執行流程和結果傳遞

到目前為止,我們已經知道如何建立、連結和執行簡單的作業。現在我們將重點轉向 method。在執行 method 時,Accelerator 會呼叫三個函式,它們分別是 prepare()、analysis() 和 synthesis()。一個 method 可以同時呼叫這三個函式,或者至少呼叫一個。

三個函式的返回值都可以儲存在作業的目錄中,並被用在其他作業上。

單機每秒最多可處理10億條資料!eBay開源資料處理框架Accelerator

資料集

資料集是 Accelerator 預設的儲存型別,專為並行處理和高效能而設計。資料集建立在作業之上,因此資料集通過 method 來建立,並儲存在作業目錄中。單個作業可以包含任意數量的資料集。

在內部,資料集中的資料以行列格式儲存。所有列都可以被獨立訪問,避免讀取到不必要的資料。資料也被分成固定數量的片段,提供並行訪問能力。資料集可能會被雜湊,雜湊函式將具有相同雜湊值的資料行組合到同一個片段中。

匯入資料

讓我們來看看匯入檔案(建立資料集)的常見操作。csvimport 方法可用於匯入許多不同的檔案型別,它可以解析大量的 CSV 格式的檔案,並將資料儲存為資料集。建立的資料集儲存在結果作業中,資料集的名稱預設為 jobid 加上字串 default,也可以使用自定義字串。

連結資料集

就像作業一樣,資料集也可以相互連結。由於資料集是建立在作業之上的,所以連結資料集就很簡單。例如,假設我們剛剛將 file0.txt 匯入 imp-0,並且 file1.txt 中儲存了更多資料。我們可以匯入後一個檔案並提供一個指向前一個資料集的連結。由於資料集已連結,現在可以使用 imp-1(或 imp-1/default)資料集引用來訪問從這兩個資料集匯入的所有資料檔案。

在處理隨時間增長的資料(如日誌資料)時,使用連結十分方便。我們可以通過連結擴充套件具有更多行的資料集,這是一個非常輕量級的操作。

將新列新增到資料集

新增列是很常用操作,Accelerator 通過連結來處理新列。

原理很簡單,假設我們有一個“源”資料集,我們要新增一個新列,只需要建立一個只包含新列的新資料集,並在建立它時讓 Accelerator 將所有源資料集的列連結到新資料集。

並行執行

Accelerator 專為並行處理而設計,主要通過分片資料集和並行 analysis() 呼叫組合來實現並行處理。

迭代器在 analysis() 函式內部執行,該函式為每個資料集片段 fork 一次。analysis() 函式的返回值將作為 synthesis() 函式的輸入。我們可以顯式地合併結果,不過 analysis_res 帶有一個相當神奇的方法 merge_auto(),它根據資料型別將所有片段的結果合併為一個。

urd

我們已經看到 Accelerator 如何跟蹤已經建立好的作業,並在必要時重用作業。這樣節省了時間並將相關的計算連結在一起,不過,在這之上還有另一個層可以進一步提高可視性和作業重用性,它就是 urd 伺服器。

urd 將作業清單及其依賴關係儲存在基於日誌檔案的資料庫中。在構建指令碼中發生的所有事情都可以記錄到 urd 中。為了做到這一點,我們需要一個名單來儲存資訊,還需要一個金鑰,而在大多數情況下還需要一個日期,方便日後查詢。

效能測試

新作業的啟動時間只有幾分之一秒。以下是一些不同作業型別的處理時間。

準備資料:匯入、型別轉換和雜湊

示例資料檔案大小為 1.1TB(壓縮後 280GB),包含 63 億行和 14 列。Accelerator 執行在具有 72 核心和快速磁碟的大型機上。

單機每秒最多可處理10億條資料!eBay開源資料處理框架Accelerator

上述數值是基於全部資料得出的。匯入作業(A):匯入 gz 壓縮檔案。有趣的是,匯入比普通的 zcat file.gz> /dev/null 要快 30%。在 FreeBSD 上,zcat 速度更快。型別轉換作業(B):5 個 json-list、5 個數字、2 個日期和 2 個 unicode 列,每行平均有 172 個位元組。該作業的讀取速度超過每秒半千兆位元組,同時儲存幾乎相同數量的資料到磁碟上,因此磁碟頻寬高於每秒 1 千兆位元組。由於雜湊速度取決於被雜湊的列,因此顯示的值(C)是四個雜湊作業的平均值。

處理資料

為了計算Σ(a×b×c),我們通過一個 method 讀取三個列、將它們的值相乘並將結果寫入新列。第二個作業為新列新增值。

單機每秒最多可處理10億條資料!eBay開源資料處理框架Accelerator

可以看到,將三個 float64 相乘並寫回到磁碟實際上是很快的——每秒 7 千 7 百萬行。將這些值彙總在一起甚至更快——每秒超過十億個值。而在 Python 中,執行同樣操作需要 6 秒。

結論

Accelerator 是一款用於快速資料處理的工具。在單機上,每秒可以處理數百萬行資料,如果任務簡單,可以每秒處理 10 億行。除了速度快之外,Accelerator 還可以減少手動管理原始檔、資料檔案、計算以及相關結果的工作。它已被成功用在多個專案中,eBay 現在正式將其開源。

相關連結:

ExpertMaker Accelerator 程式碼倉庫 (https://github.com/eBay/accelerator)

Installer 倉庫 (https://github.com/eBay/accelerator-project_skeleton)

Accelerator 使用者參考手冊 (https://berkeman.github.io/pdf/acc_manual.pdf)


更多幹貨內容請關注微信公眾號“AI 前線”,(ID:ai-front)


相關文章