Scuba,Facebook的一個很是快速、分佈式的內存數據庫,用於實時分析和查詢。是Facebook的迴歸分析代碼、錯誤報告監控、廣告收入監控和性能調試的背後主力。數據庫
隨着雲計算大數據的發展,有愈來愈多的場景須要藉助於實時數據處理技術,爲此有不少公司開發了本身的實時處理系統,Facebook就是其中的一員,他們構建的實時數據處理生態系統每秒鐘可以處理數百GB的數據。本文介紹了Facebook在設計該系統時從易用性、性能、容錯、可伸縮性以及正確性等方面考慮所作的重要設計決策,這些決策和系統如何知足秒級的延遲需求,以及在構建該系統的過程當中Facebook所總結的經驗教訓。編程
Facebook認爲在設計一個實時數據處理系統的時候首先要想清楚下面5個問題:架構
針對這些問題,Facebook提出了5個設計決策:語言範式、數據傳輸、處理語義、狀態保存機制以及數據再處理。下面的圖表展現了每個設計決策對數據質量屬性的影響:框架
以及不一樣的流處理系統所作的設計決策:運維
語言範式決定了編寫應用程序的難易程度以及開發者對性能的操控程度。基本有三種選擇:聲明式,函數式以及過程式編程語言。對於Facebook而言,單一的某種語言沒法知足全部的用例,所以他們開發了三種不一樣的流處理系統。
數據傳輸對流處理系統的容錯性、性能和可伸縮性都有很是大的影響,傳統的數據傳輸方式包括:直接消息傳輸、基於代理的消息傳輸和基於持久化存儲的消息傳輸。Facebook使用Scribe,一種持久化的消息總線,來鏈接不一樣的處理節點。
處理語義包括狀態語義(每個輸入事件最少被計數一次、最多被計數一次仍是隻被計數一次?)和輸出語義(給定的輸出值在輸出流中最少出現一次、最多出現一次仍是隻出現一次?)。其中無狀態的處理器只有輸出語義,而有狀態的處理器這兩種語義都有。Facebook對不一樣的應用一般有不一樣的狀態和輸出語義需求,於是開發了Puma、Stylus和Swift三個支持不一樣語義的系統。
狀態保存機制的實現方式有不少,包括複製副本、本地數據庫持久化、遠程數據庫持久化、上游備份以及全局一致性快照等。Facebook實現了兩種狀態保存機制,其中Puma實現了遠程數據庫存儲,而Stylus則實現了本地和遠程數據庫存儲。
再處理的方式有三種:僅使用流處理;維護兩個單獨的系統,一個用於流處理,一個用於批處理;開發一個可以在批處理環境中運行的流處理系統。Facebook採用了一種與Spark Streaming以及Flink都不一樣的處理方式,他們使用標準的MapReduce框架從Hive中讀取數據並在批處理環境中運行流處理應用程序。Puma應用能夠運行在Hive環境中,而Stylus則提供了三種類型的處理器:無狀態的處理器,通用的有狀態的處理器和一個居中的流處理器。編程語言
在系統建設方面,Facebook的主要設計目標是秒級的延遲,每秒鐘可以處理幾百GB的數據,爲此他們經過一個持久化消息總線將全部的處理組件鏈接起來進行數據傳輸,同時也將數據的處理和傳輸解耦,實現容錯、可伸縮、易用性和正確性。整個系統的架構圖以下:分佈式
該圖闡述了Facebook實時處理系統的數據流,數據從左側的移動和Web產品中產生,而後被送入Scribe(一個分佈式數據傳輸系統),而Puma、Stylus和Swift等實時流處理系統則從Scribe中讀取數據並將處理結果寫入Scribe。Puma、Stylus和Swift能夠根據須要經過Scribe鏈接成一個複雜的DAG(有向無環圖)。函數
接下來是使用該實時處理系統的一個示例應用,該應用識別一個輸入事件流中的趨勢事件,以5分鐘爲單位對這段時間內產生的話題按事件數排序。每一個事件包含一個事件類型,一個維度ID(用於獲取事件的維度信息,例如使用的編程語言)和一個文本(用於分類事件主題,例如電影或者嬰兒)。該應用有4個處理節點,每個均可以並行執行,總體流程圖以下:性能
在該圖中,Filterer會根據事件類型過濾輸入流,而後將輸出按照維度ID進行分片,這樣下一個節點就可以並行處理分片數據了。Joiner經過維度ID從一個或者多個外部系統檢索信息,而後根據事件的文本內容對其按照話題進行分類。Scorer記錄着最近一段時間內每個話題的事件數,同時還會跟蹤這些計數器的長期趨勢。Ranker則計算每N分鐘每個話題的前K個事件是什麼。測試
最後是Facebook在構建該系統的過程總結的一些經驗教訓:首先,沒有一個單獨的流處理系統可以適應全部場景,針對不一樣的點使用不一樣的系統才能更好地解決問題;其次易用性不只包括使用,還包括開發、調試、部署、監控和運維等方面;最後,流處理和批處理並非互斥的,組合使用這兩種系統可以加速數據的處理速度。