七牛大資料平臺的演進

七牛雲發表於2017-09-12

看著圖 1 大家可能會感到熟悉,又或者會覺得部分有些陌生,這是一張彙集了目前大資料生態下大多數成熟元件的架構圖。眾所周知,大資料生態很複雜,對於個人來說,要全部學會可能要花費好幾年時間。而對於企業來說,要最大程度發揮其價值,構建一個成熟穩定、功能多樣的大資料平臺,期間花費的時間以及人力成本著實難以估量,更何況還需要考慮持續維護的問題。這就是七牛的Pandora大資料平臺靈感的來源,我們構建一個大資料平臺,作為產品提供給使用者,快速幫助使用者挖掘資料價值。

1. Pandora的背景和解決的問題

七牛是以雲端儲存起家的公司,平臺上有著大量的資料、業務日誌以及運維監控資料,基於對這些資料的管理以及分析的需求,Pandora誕生了。我們搭建了一個可靠的大資料平臺,將大資料生態中的各個元件配套成一個體系發揮作用,用來解決實際業務中碰到的繁瑣、複雜、多樣化的問題。這個大資料平臺的工作從資料的採集便已開始,通過一條資料匯流排,再根據業務需求分流到不同的下游產品,從儲存到資料視覺化,從實時的資料變換到離線的演算法分析,我們構建一個全棧的大資料分析產品。

與此同時,我們在大資料平臺之上構建了業務工作流的概念,讓使用者只需關心構建符合他們業務模型的工作流,而無需具備大資料技術背景。不僅大大降低了使用者挖掘大資料價值的成本,更為重要的是去除了大資料技術門檻,使得各行各業的專家可以更好的施展自己對業務的深度理解。

在工作流上,使用者不僅可以清晰的監控自己的資料流動,輕鬆構建各類實時、離線的資料變化與自定義計算,還可以按需彈性擴容、快速排程雲端資源,降低了運維的成本。與此同時,我們整合了社群中大量的優秀開源軟體,對其進行優化及定製,一方面以便發揮其更強大的功能,另一方面,也讓熟悉使用這類開源軟體的使用者可以做到快速遷移,無縫切換使用。

2. Pandora的功能特點與應用場景

那麼,Pandora到底是一個怎樣的平臺呢?工作流又是怎樣的呢?讓我們首先來直觀的看一下工作流的使用形態,如圖 2 所示。

圖 2 工作流形態
圖 2 工作流形態

最左邊的資料來源是工作流的起點,資料來源可以是一個,也可以是多個。在實時計算的工作流中,我們只能有一個資料來源,這個資料來源就是資料收集匯聚的中心,也可以理解為資料匯流排,所有不同終端的資料打向資料來源,再通過資料來源根據業務需求分發到不同下游;在離線工作流中,我們可以有多個資料來源,不同的資料來源代表的是儲存在不同地方的離線資料,可以是七牛雲端儲存中的不同檔案,又或是HDFS等不同型別的資料倉儲。

不管是實時還是離線,從資料來源開始,你就可以根據需要做不同型別的處理。

最基本的處理是對資料進行一些定製化的計算,比如你可能需要對每天海量的資料進行一個定時分析匯聚的功能,計算每分鐘有多少條資料、每小時有多少條資料,從而縮減資料規模節約儲存成本,或者從中生成一份資料日報、週報等等;又比如在這個資訊爆炸的時代,你從網上抓取了海量的資料,需要對資料進行一些清洗、過濾、刪選,以此分析社會熱點或其他有價值的資訊;又比如你想對資料做一個延伸或擴充套件,最常見的就是對一個IP獲取它的運營商、所在區域等資訊。那麼你就可以建立一個計算任務,最簡單的編寫一些SQL語句就可以做資料變換;進階一些的使用方式就是編寫一些UDF(使用者自定義的函式),做一些較為複雜的變化;更高階的就是直接編寫一類外掛,直接使用大量Java的類庫對資料進行操作。當然,在離線計算中,除了單個資料來源的計算任務以外,你還可以對兩個資料來源,亦或是兩個計算任務的結果進行聚合,然後再進行計算等等。計算任務可以滿足你對於整個工作流的完整資料處理需求。

在進行過一個基本的計算以後,可能最常見的一個需求就是對這些計算後的資料進行檢索,直白的說就可以查詢你的資料。那麼你可以建立一個匯出到日誌檢索,在這裡你就可以搜尋你的計算結果。當然,你的資料在資料來源中也完全可以不經過任何計算任務,直接導向日誌檢索。又或者你希望對資料進行更完善的實時監控和資料視覺化處理,那麼就可以匯出到時序資料庫,針對帶有時間戳的資料做高效能資料寫入和查詢優化,滿足你針對實時海量資料的即席查詢需求。

另一方面,你工作流計算後的結果,可以直接再次匯出到七牛雲端儲存進行永久儲存,或者與後續的資料結合進行分析。你也可以理解為通過大資料服務,七牛的雲端儲存變成了一個資料倉儲為客戶提供服務。之前已經儲存在七牛雲上的資料(如CDN日誌等),完全可以直接使用我們的大資料平臺進行計算,無需任何接入過程。

為了方便使用者充分利用自己的資料,我們甚至提供了匯出到 HTTP 服務,使用者可以構建自己的 HTTP 伺服器來接受經過Pandora大資料平臺計算後的資料。

3. Pandora的系統架構與變遷

(圖 3 產品架構圖)
(圖 3 產品架構圖)

圖 3 是 Pandora的產品架構圖,基本的功能在第 2 節中均已介紹,在此不再贅述,在講解系統架構之前,讓我們對照產品架構進行一些基本的系統元件技術名稱的對照說明,以便下文描述簡潔便於理解。資料通過我們提供的資料上報工具logkit、各類SDK或者使用者直接呼叫開放API接入,資料進入後無論是資料來源本身還是經過計算任務後的臨時資料儲存節點,我們都一稱作訊息佇列,技術上稱之為Pipeline,像不同下游提供匯出服務的元件我們稱之為Export,在Pipeline中承擔各類計算任務處理的元件我們稱之為Transform,下游的時序資料庫服務我們稱之為TSDB,下游的日誌檢索服務我們稱之為LogDB。

圖 4 Pandora系統架構圖
圖 4 Pandora系統架構圖

有了這些基本概念後,讓我們對照圖 4 Panora系統架構圖,開啟我們的Pandora架構演進之旅。

3.1 資料上報

最左側的元件是資料收集的部分,資料來源於客戶各種各樣的系統。相信大部分使用者在接入大資料平臺時,都會面臨資料收集這一難題,一方面希望資料不重不漏全部收集上來,一方面又要資料收集儘可能高效且不太消耗機器的各類資源,同時還要滿足場景各異的不同情況下的資料收集需求。熟悉這塊的朋友可能也早已瞭解,社群已經有很多不同型別的開源資料收集工具,知名的包括flume、logstash、fluentd、telegraf等等,他們各有利弊,功能上大都滿足需求,但是在效能上和一些非通用需求的場景上不盡如人意。為了更好的滿足使用者不同型別的需求,我們自主研發了一個可以收集各種各樣資料來源資料的工具logkit,圖 5 是logkit的功能架構示意圖。logkit使用go語言編寫,以外掛的形式定製不同的資料收集解析需求,處理高效、效能損耗低,同時也已經開源,我們非常歡迎大家一起參與到logkit的使用和程式碼開發定製中來,為logkit 提提PR,當然,也非常樂意接受您關於logkit的任何意見或建議,只需在github提issues即可。

圖 5 logkit功能架構示意圖
圖 5 logkit功能架構示意圖

有了這樣一款資料收集工具,幾乎 90% 的資料收集場景我們已經解決了,但是還會有諸如ios、android客戶端資料直接上報、頁面請求點選資料直接上報等需求,為此我們提供了各類語言的SDK方便使用者使用,以彌補logkit功能上無法滿足的需求。

3.2 大資料匯流排Pipline

資料收集上來後,就正式進入我們的Pandora大資料平臺了。所有上報的資料無論最終是否計算或儲存,都會統一暫存進入我們的大資料匯流排Pipeline。相信經過上面的介紹,很多讀者早已發現,Pandora幫助使用者根據不同場景選擇最適合的大資料分析方式。而這套模式的核心,毋庸置疑,就是處理資料在不同大資料產品間的流轉。
Pipeline就是這樣一條資料匯流排,在資料匯流排的基礎上我們打通一條條管,根據所需的場景匯出到後端相應的儲存服務上。同時據此來進行資源分配和任務管理。這樣一來,就可以避免使用者技術選型及技術架構與使用姿勢和業務場景不匹配的情況,同時也可以利用雲端計算的優勢,按需分配、快速擴容。

3.2.1 基於confluent的初版

圖 6 Pipeline第一版
圖 6 Pipeline第一版

如圖 6 所示是我們的第一版架構,實現上我們通過定製開源版本的confluent,並把它作為我們這個架構系統的核心。資料要流入系統,我們首先構建了一個 Points Gate(API 伺服器),Points Gate 解析校驗使用者的資料格式並呼叫confluent中kafka-Rest提供的rest API 將資料寫入到kafka,利用schema-registry完成資料格式的校驗以及資料解析,通過kafka獲得資料管道的能力。

在進行後設資料建立時,我們的排程器在後設資料伺服器上建立一個使用者後設資料儲存在MongoDB當中。對於MongoDB的後設資料訪問,我們構建了一個二級快取系統(即圖中qconf),資料在進入或者匯出時都會通過二級快取訪問後設資料,這樣資料就可以快速得到校驗,扛住海量的資料吞吐。Kafka本身包含了Zookeeper元件,我們也藉此來保證整體系統元件的服務發現以及資料一致性這兩個問題。

然而,隨著應用的增加,資料量越來越大,這樣,單個定製版的 Confluent 並不能滿足這些資料量增長的業務壓力,以及使用者不斷增加的場景需求。kafka topic(partition)不斷增長導致整體響應變慢,無法快速切換災備等待問題日益凸顯。在這個基礎上,我們對原本的系統架構進行了調整。

3.2.2 Pipeline的升級

圖 7 pipeline的升級
圖 7 pipeline的升級

如圖 7 所示,我們對Pipeline的第一次整體升級包含了大量的元件基礎架構的調整。首先我們構建了Confluent的多叢集系統,將單個Confluent叢集規模控制在100臺機器以內,分割槽數量控制在1萬以內,根據需求對叢集進行路由。

可見通過多叢集系統,我們可以合理控制每個confluent叢集的規模,同時根據我們的排程器按照需要切換使用者到不同的叢集上,實現快速切換、擴容、容災、隔離等排程需求。

其次我們對Points Gate、Transform、Export中無狀態元件進行了容器化處理,利用我們七牛內部的容器雲平臺,實現了無狀態服務的快速部署、擴容以及灰度釋出等需求。

這次架構的調整效果顯著,我們成功抗住了每天上百TB,千億級資料點的資料增量。

不止於此,為了更高的效能提升以及節約成本,我們在上述升級之後進行了第二次的架構升級。這次升級主要體現在對Confluent的進一步定製(或者說替換),我們不再使用kafka-rest,同時對打點的資料格式進一步優化,又一次節約了近一半的機器成本。

3.3 資料匯出服務Export

在解決了資料匯流排問題以後,問題的重中之重自然是如何處理資料匯出的問題。眾所周知,資料匯出其實就是從一個上游系統拉取資料,然後將資料再傳送到下游系統的過程。但這裡面涉及的難點和調整可能大多數都是不為人知的了。在介紹我們的匯出服務架構之前,非常有必要描述一下針對海量資料匯出,到底有哪些挑戰?

3.3.1 資料匯出的挑戰

首先面對的第一大挑戰自然是高吞吐量的問題,海量資料不斷湧入帶來的必然問題就是網路卡和CPU分配的問題,一旦流量分配不均,就會出現大量因網路卡、CPU負載過高帶來的延遲,嚴重影響服務可用性。

顯然,保證低延遲就是第二個挑戰,一旦各個鏈路有一個環節配合不均衡,就會帶來大量延遲,如何保證匯出的上下游始終保持較高的吞吐量,從而保證較低的延遲,是一個非常大的調整。

為了保證低延遲,就要更好地適配多種下游,使其始終保證高吞吐,瞭解下游不同服務的特性,並針對這些特性動態的調整資源,亦是一個很大的挑戰。

除此之外還有分散式系統的常見問題,需要保證服務高可用,以及水平擴充套件的能力。保證任務單元標準化,任務粒度可以切分擴充套件;保證排程任務節點故障不影響其他節點的正常匯出等等。

最為重要的是自動化運維,當匯出的任務涵蓋數十上百臺機器後,人力已經無法精細化處理每臺機器的任務分配,資源必須可以自動排程、調整以及構建統一的任務監控。

3.3.2 匯出服務功能介紹及架構演進

圖 8 匯出服務功能架構圖
圖 8 匯出服務功能架構圖
]

讓我們來看一下匯出服務的功能架構圖,如圖 8 所示。我們的匯出服務主要涉及三個層級,一個是後設資料管理,在這一層保證任務的分配以及監控展示;第二層則是任務管理層,除了基本的任務切分、併發管理以及通訊協議之外,還包含了壓力預估模組,根據之前的資料量預估下一階段的資料流量,從而調整資源分配;再下一層則是資料處理層,在這一層完成諸如資料預取、資料校驗、壓縮以及推送到下游等任務。

在最初的版本中,我們會在 zookeeper 上面建立一個任務(task) ,Export 通過分散式鎖對task進行爭搶,被搶到的任務則開始直接匯出,如圖 9 所示。

圖 9 初版匯出服務架構
圖 9 初版匯出服務架構

在這樣一個初步架構中,我們基本完成了水平擴充套件以及高可用的需求,同時做了諸如資料預取,延遲報警、資料監控等多種功能和優化。但是流量上來以後,很容易出現某個機器爭取的任務流量變大,導致大量資料打到同一臺機器上,導致網路卡和CPU負載過高,延遲急劇升高。本質上就是流量分佈不均勻,導致匯出效能低下,機器資源的平均利用率也低。

此時,我們對該方案進行第一次架構升級,如圖 10 所示。我們將原來topic級別的任務按照parition進行分散式消費。為了使得每個partition粒度的任務大體是均等的,我們將partition承載的資料量按照標準化處理,並根據歷史流量進行預測,預測結果超過當前我們定製的標準符合的對應容量即觸發擴容,這樣的標準化有效簡化了排程的難度。

同時我們將原來純粹的export改為master/worker結構,Master對收集到的任務進行主動權衡分配,根據任務的歷史流量進行流量預測、對任務的partition數量、每個export worker的機器資源剩餘情況,進行綜合排程。對於一些特殊任務做機器黑白名單繫結等功能。

圖 11 第二次架構升級的匯出服務
圖 11 第二次架構升級的匯出服務

在做了上述工作以後,我們機器的整體利用率有了很大的提升,但是由於下游系統的不同,寫入吞吐量始終參差不齊,無法始終保持在一個較高的水平。為了解決該問題,我們再次對架構進行小範圍升級,如圖 11 所示,我們在匯出的export worker端增加了一套對下游系統的適配加速模組。其核心思路就是按照下游的吞吐能力進行自動調節請求體大小以及併發度。這個主要是為了解決上下游傳輸資料速度不匹配,以及下游吞吐量不穩定的問題。

類似於Flume的思想,我們構建了一個記憶體佇列,以事務的形式從佇列中獲取資料(或者失敗回滾),根據下游的情況調整單次資料請求的大小和併發度,以及調整出錯等待時間等。這樣一來,整個匯出的吞吐量就可以很有效的進行控制,去除了毛刺,極大的提高了機器資源的使用率以及匯出效率。
解決了資料的匯出問題,基本上絕大部分資料流轉的問題也都解決了。下面我們開始關注Pandora下游的一系列服務。

3.4 時序資料庫服務TSDB

TSDB是七牛完全自主研發的分散式時序資料庫服務。TSDB針對時序資料定製儲存引擎,根據時序資料帶有時間戳的特性,我們針對時間戳做特殊的索引,實現資料高速匯入和實時查詢獲取的能力;同時構建了簡單且高效能的HTTP寫點和查詢介面,為查詢聚合資料量身定製了類SQL語言,完全相容開源社群InfluxDB的API,支援無縫對接到Grafana,對資料進行高比例壓縮,實現低成本儲存。除此之外,TSDB擁有開源社群版本的InfluxDB所沒有的分散式、多叢集、高可用,水平擴容、以及分庫分表能力。

圖 12 TSDB 基本結構示意圖
圖 12 TSDB 基本結構示意圖

如圖 12 所示,TSDB是我們基於tsm構建的分散式時序資料庫,擁有每秒60萬條記錄的寫入效能以及實時查詢聚合分析的能力。在分散式方面,除了基本的多叢集、多租戶隔離的概念以外,我們還針對性的做了兩個強大的擴容功能,一個是根據時序進行縱向叢集切割,解決海量資料寫入時磁碟的快速擴容問題;另一個則是根據使用者的標籤進行資料庫表橫向切割,類似傳統資料的分庫分表能力。在進行了這兩大擴充套件能力變換後,資料的寫入和查詢依舊高效,甚至查詢速度在分庫分表後效能有所提升。

為了實現這樣的擴容功能,我們基於此構建了一個分散式計算引擎,解析使用者的SQL並變成一個個執行計劃,將執行計劃下推至不同的TSM計算引擎例項中進行計算,最後再進行資料reduce計算反饋給使用者。

除了資料寫入效能高以外,還支援資料即時查詢,資料寫入成功即可查詢,資料零延遲;同時支援InfluxDB的持續聚合功能,類似於定時任務一樣將持續寫入的資料不斷進行聚合計算;當單個使用者資料量過大時,擁有橫向擴充能力,叢集擴充套件後寫入效能不打折,查詢效率更高。針對時序資料的特性,我們將資料進行冷熱分離, 對資料按照時間分片,使最近的資料查詢效能更高。

3.5 日誌檢索服務LogDB

在瞭解完我們的時序資料庫以後,讓我們來看一下下游的另一大服務,日誌檢索服務,又稱LogDB。日誌搜尋其實是幾乎所有技術開發人員都會需要的服務,傳統解決方案(ELK,Elasticsearch、Logstash、Kibana) 針對小資料量不會出現任何問題。但是當資料量過於龐大時,這些方案也就不那麼適用了。

我們LogDB的底層可以通過外掛的形式接入不同型別的搜尋引擎,包括Solr、Elasticsearch(簡稱ES)等,目前承載海量資料搜尋任務的底層引擎主要使用的是ES。與單純的使用ES不同,LogDB本身是一套分散式系統,管理的單元可以是一個ES節點,也可以是一個ES叢集,所以我們構建了大量的ES叢集,不同的叢集用以適配不同的使用者以及不同的搜尋需求。

大體上我們將搜尋的需求分為兩類,一類是ELK類需求,針對如程式執行日誌、業務訪問日誌等收集索引,這類需求的普遍特點是資料量大,時效性高,帶有時間戳,無需儲存太長時間,無需更新;另一類需求類似於搜尋引擎,資料存在更新需要,且強依賴於不同型別的分詞器,資料冷熱不明顯,不帶有明顯的時間屬性,我們稱之為通用檢索需求。這兩類需求,LogDB都是完全支援的,但是針對這兩類需求,我們做的優化不同。

圖 13 LogDB架構圖
圖 13 LogDB架構圖

在我們討論具體的優化之前,讓我們先來看一下LogDB的架構圖, 如圖 13 所示。首先是資料的寫入,LogDB是Pandora平臺下游服務,上游主要是之前提到的Pipeline以及Export。Export匯出的資料通過apisever將資料匯入到不同的ES叢集當中,根據不同使用者的需求給他們提供不同的叢集服務,叢集之間也可以相互進行切換。

那麼如何確認資料到底資料哪個叢集呢?為了使得海量的資料快速確認,我們對後設資料進行了多級快取,包括MongoDB的實際儲存、memcached的二級快取,以及本地的快取,極大提高了資料校驗的速度。除此之外,LogDB本身也是Pandora的使用者,使用了TSDB對自身資料進行監控,使用七牛雲端儲存進行資料快照與備份。同時將計費資料匯出到雲端儲存,利用我們的XSpark機器進行離線計算。

架構中剩下的部分都是我們針對不同索引做的優化。簡而言之,我們首先構建了一個高效能佇列,可以讓外部的資料持續高吞吐寫入;同時我們還會根據歷史流量進行動態索引平衡、不同叢集的索引跨叢集平衡、索引定時清理、VIP叢集隔離等功能;並且會對 ES 的搜尋進行分步搜尋控制,快取歷史搜尋,優化使用者搜尋的效率和體驗等等.

3.6 XSpark

最後有讀者看到這裡,也許會忍不住想問,如果只是純粹的想使用一個高度靈活的Spark叢集,不希望經過Pandora各類複雜的計算、匯出,甚至資料都沒儲存在七牛,可不可以享受七牛的Spark大資料服務呢?是的,完全可以,這就是我們的XSpark!

XSpark不僅與Pandora整體完全打通,可以把七牛雲端儲存當成一個資料倉儲使用,又完全可以獨立使用。即使用者除了在Pipeline裡面做離線計算之外,你還可以選擇直接一鍵生成一個基於容器雲的個人專屬Spark叢集,直接讀取你自己的資料來源,只要Spark支援的資料格式,XSpark都支援。如果你的資料已經儲存在七牛雲端儲存上,XSpark可以直接高效讀取並計算,XSpark是Pandora提供給大資料高階使用者的一個高度靈活的離線計算產品。

顯然,容器雲所具有的優勢XSpark全都具備,你完全可以根據需要動態伸縮的XSpark資源數量與規格,按需啟停等等。

圖 14 XSpark 架構圖
圖 14 XSpark 架構圖

圖 14 是 XSpark 的架構圖。我們將Spark的master和worker分為不同的容器,首先啟動Spark的master容器,獲取master地址,然後再根據使用者的配置,啟動相應數量的worker容器,worker容器自動向master註冊。同時容器雲的支撐使得我們的XSpark可以在執行過程中進行縮容擴容。

同時XSpark也開放了完整的Spark監控以及管理控制頁面,完全相容開源社群的Zepplin使用方式。


  • 下期分享:七牛大資料平臺的分析實踐

相關文章