中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

時間序列大數(shù)據(jù)平臺建設(shè)經(jīng)驗談

2018-10-16    來源:raincent

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

引言

在大數(shù)據(jù)的生態(tài)系統(tǒng)里,時間序列數(shù)據(jù)(Time Series Data,簡稱TSD)是很常見也是所占比例最大的一類數(shù)據(jù),幾乎出現(xiàn)在科學和工程的各個領(lǐng)域,一些常見的時間序列數(shù)據(jù)有:描述服務(wù)器運行狀況的Metrics數(shù)據(jù)、各種IoT系統(tǒng)的終端數(shù)據(jù)、腦電圖、匯率、股價、氣象和天文數(shù)據(jù)等等,時序數(shù)據(jù)在數(shù)據(jù)特征和處理方式上有很大的共性,因此也催生了一些面向面向時序數(shù)據(jù)的特定工具,比如時序數(shù)據(jù)庫和時序數(shù)據(jù)可視化工具等等,在云平臺上也開始出現(xiàn)面向時序數(shù)據(jù)的SaaS/PaaS服務(wù),例如微軟最近剛剛發(fā)布的Azure Time Series Insight。本文會介紹一個時間序列數(shù)據(jù)處理平臺案例,探討這類大數(shù)據(jù)平臺在架構(gòu)、選型和設(shè)計上的一些實踐經(jīng)驗以供參考。

業(yè)務(wù)場景

本文介紹的案例是一個面向大型企業(yè)IT系統(tǒng)運維的監(jiān)控平臺,數(shù)據(jù)來源于多種監(jiān)控終端產(chǎn)生的時序數(shù)據(jù),涉及的數(shù)據(jù)源涵蓋了SCOM、AppDynamics、Website Pulse、Piwik以及AWS Cloud Watch等多種主流的第三方監(jiān)控工具,基于組織內(nèi)部的IT規(guī)范,所有應(yīng)用系統(tǒng)都安裝了上述一種或多種監(jiān)控工具,這為建立一個統(tǒng)一的多維度的監(jiān)控平臺提供了保證,該平臺基于多種監(jiān)控數(shù)據(jù),對同一應(yīng)用/服務(wù)系統(tǒng)進行綜合的健康評估,在發(fā)生故障時會根據(jù)不同的數(shù)據(jù)源進行交叉驗證,從而幫助運維人員快速和準確地定位故障原因。

架構(gòu)設(shè)計

完整的大數(shù)據(jù)系統(tǒng)往往包涵數(shù)據(jù)采集,消息對列,實時流處理,離線批處理,數(shù)據(jù)存儲和數(shù)據(jù)展示等多個組件,為了滿足業(yè)務(wù)上對實時監(jiān)控和歷史數(shù)據(jù)匯總分析的需求,系統(tǒng)遵循了Lambda架構(gòu),將實時流處理與離線批處理進行了分離。此外,鑒于平臺處理的所有數(shù)據(jù)均為時序數(shù)據(jù),在架構(gòu)上針對這個特點著重進行了調(diào)整和優(yōu)化,其中重要的一環(huán)是引入“時間序列數(shù)據(jù)庫”作為核心的數(shù)據(jù)存儲與查詢引擎。

系統(tǒng)完整的數(shù)據(jù)流如下:首先,數(shù)據(jù)被數(shù)據(jù)采集組件從外部系統(tǒng)采集并來放入消息隊列,接著,流處理組件從隊列中取出數(shù)據(jù)進行流式計算,消息隊列從中的起到的作用是平衡“生產(chǎn)者”——數(shù)據(jù)采集組件和“消費者”——流處理組件在消息處理上的速率差,提升系統(tǒng)的穩(wěn)定性和可靠性。數(shù)據(jù)在流處理組件中會經(jīng)歷清洗、過濾、轉(zhuǎn)換、業(yè)務(wù)處理等諸多環(huán)節(jié),之后按TSD引擎規(guī)定的標準TSD格式推送到TSD引擎,由TSD引擎最終寫入后端數(shù)據(jù)庫。

實時流處理部分要求數(shù)據(jù)從采集到最后的展示控制在秒級延遲,嚴格來說,這是一套近實時系統(tǒng),但其實時性已經(jīng)足夠滿足業(yè)務(wù)上的需求,為了保證處理速率,實時鏈條上的數(shù)據(jù)大多數(shù)時間是駐留在內(nèi)存中的,好在實時部分只關(guān)注近兩周的數(shù)據(jù),所以總的內(nèi)存消耗處在可控的范圍之內(nèi)。

在批處理數(shù)據(jù)線上,利用數(shù)據(jù)庫的同步機制將實時部分落地的數(shù)據(jù)持續(xù)同步到批處理的數(shù)據(jù)庫上,這個庫存儲著數(shù)據(jù)全集,所有批處理相關(guān)的查詢都在這個庫上執(zhí)行,與實時部分的組件完全隔離。批處理會保存過去三年的數(shù)據(jù),分析尺度多為日,周,月甚至年。不同于一般離線分析系統(tǒng)選型Hive一類的數(shù)據(jù)倉庫,我們希望在離線分析時繼續(xù)充分利用時序數(shù)據(jù)庫帶來的種種好處,比如經(jīng)過特殊優(yōu)化的時序數(shù)據(jù)查詢,開箱即用的查詢接口等等,所以在離線部分我們依然配備TSD引擎,批處理組件在實現(xiàn)業(yè)務(wù)需求時可以深度利用TSD引擎對時序數(shù)據(jù)進行聚合運算,在聚合之后的結(jié)果上再進行更加復雜的分析并寫回數(shù)據(jù)庫,同時也可以在普通查詢無法實現(xiàn)需求時越過TSD引擎直接對底層數(shù)據(jù)文件進行MR計算。

最后,數(shù)據(jù)展示組件會從TSD引擎中提取數(shù)據(jù),以各種形式的圖表展示給用戶。在實際的開發(fā)中我們發(fā)現(xiàn)TSD引擎對數(shù)據(jù)格式有諸多的限制,有的TSD需要進行某些轉(zhuǎn)換和適配才能展示,因此我們在TSD引擎和數(shù)據(jù)展示組件中間引入了一個輕量的驅(qū)動程序來透明地解決這些問題。

基于上述分析和實際的原型驗證,在多輪迭代之后,我們最終成形的系統(tǒng)架構(gòu)如下:

 

 

接下去我們會對每個組件逐一進行介紹。

組件與選型

數(shù)據(jù)采集

平臺的數(shù)據(jù)來源非常多,涉及到的協(xié)議類型自然就多,并且伴隨著以后的持續(xù)建設(shè),會有越來越多新的數(shù)據(jù)源和傳輸協(xié)議需要被支持,因此我們希望選定的組件能夠支持非常豐富的協(xié)議類型,同時盡可能地通過配置去集成數(shù)據(jù)源并采集數(shù)據(jù),避免編寫大量的代碼。目前業(yè)界較為主流的數(shù)據(jù)采集工具有Flume、Logstash以及Kafka Connect等等,這些工具各有各的特點和擅長領(lǐng)域,但是在支持協(xié)議的豐富性和可配置性上,與我們的需求有一定的差距。

其實有一個一直被人忽視但卻是非常理想的數(shù)據(jù)采集組件——Apache Camel,它主要應(yīng)用于企業(yè)應(yīng)用集成領(lǐng)域,也被一些系統(tǒng)作為ESB(企業(yè)服務(wù)總線)使用,其作用是在應(yīng)用系統(tǒng)林立的企業(yè)IT環(huán)境中扮演一個“萬向接頭”的角色,讓數(shù)據(jù)和信息在各種不同的系統(tǒng)間平滑地交換和流轉(zhuǎn),經(jīng)過多年的積累,Camel已經(jīng)支持近200種協(xié)議或數(shù)據(jù)源,并且可以完全基于配置實現(xiàn),這恰好滿足了我們數(shù)據(jù)采集的需求,經(jīng)過原型驗證,也證明了我們的選擇是明智的。

最后,作為一個非大數(shù)據(jù)組件,對于Camel的性能和吞吐量我們是有清晰認識的,通過對數(shù)據(jù)源進行分組,使用多個Camel實例分區(qū)采集數(shù)據(jù),我們從架構(gòu)上輕松地解決了這些問題。

消息隊列

在消息隊列的選擇上沒有可以討論的,Kafka幾乎是不二的選擇,我們也不例外。

流處理

流處理和批處理都是業(yè)務(wù)邏輯最集中的地方,也是系統(tǒng)的核心。目前用于流處理的主流技術(shù)是Storm和Spark Streaming,對兩者進行比較的文章很多,通常認為Storm具有更高的實時性,可以做到最低亞秒級的延遲,相比之下Spark Streaming的實時性要差一些,因為它以”micro batch”的方式進行流處理的,但是依托Spark這個大平臺,從統(tǒng)一技術(shù)堆棧和與其他Spark組件交互的角度考慮,Spark Streaming變得越來越流行,鑒于在業(yè)務(wù)上秒級延遲已經(jīng)可以滿足需求,我們最終選擇了后者。

批處理

傳統(tǒng)大數(shù)據(jù)的離線處理多選擇以Hive為代表的數(shù)據(jù)倉庫進行建模和分析,這在很多項目上被證明是可靠的解決方案。后來隨著Spark的不斷壯大,Spark SQL的使用越來越廣泛,并且Spark SQL完全兼容Hive,這使得遷移工作幾乎沒有任何障礙。對于復雜的非結(jié)構(gòu)化數(shù)據(jù),Hadoop平臺上通過MR編程去處理,Spark是通過Spark Core的RDD編程實現(xiàn)。如今Spark在大數(shù)據(jù)處理的很多方面已經(jīng)取代Hadoop成為大數(shù)據(jù)的首選技術(shù)平臺,我們在批處理的選型上也沒有過多的討論,使用Spark Core + Spark SQL是一個自然而然的決定。

但是考慮到系統(tǒng)處理的是TSD數(shù)據(jù),如前文所屬,在批處理的數(shù)據(jù)鏈條上,TSD引擎依然是一個必不可少的角色,我們設(shè)計的策略是:

所有TSD引擎可以直接支持的查詢交由TSD引擎直接處理

復雜的業(yè)務(wù)處理可以通過TSD引擎進行預(yù)處理,將預(yù)處理結(jié)果交給Spark Core進行深度分析并將結(jié)果寫回數(shù)據(jù)庫

針對TSD引擎無法完成的分析邏輯,由Spark Core或Spark SQL繞過TSD引擎,直連后端的HBase進行分析處理,結(jié)果同樣直接寫到HBase上

為提升性能,對分析中使用到的以日/周/月/年為單位的中間表進行預(yù)生成計算。

主數(shù)據(jù)管理

主數(shù)據(jù)是指來自數(shù)據(jù)源的核心業(yè)務(wù)對象,對于我們這個以監(jiān)控為核心的平臺,主數(shù)據(jù)包括:服務(wù)器、系統(tǒng)拓撲結(jié)構(gòu)、站點、網(wǎng)絡(luò)設(shè)施等等,主數(shù)據(jù)往往都跨越多種不同的數(shù)據(jù)源,并且經(jīng)常發(fā)生變更,需要對其進行定期維護。

為此,我們構(gòu)建了一個統(tǒng)一的主數(shù)據(jù)管理組件,并通過Web Service的方式向外提供主數(shù)據(jù),由于平臺在流處理和批處理過程中需要頻繁地使用主數(shù)據(jù),而主數(shù)據(jù)的體量并不大,所以我們會讓流處理和批處理組件一次性地將主數(shù)據(jù)加載到內(nèi)存中,同時為它們加入命令行和Restful API接口,允許它們在主數(shù)據(jù)發(fā)生變更時重新加載主數(shù)據(jù)。

主數(shù)據(jù)管理模塊是一個傳統(tǒng)的Web應(yīng)用,基于Spring-Boot構(gòu)建,使用MySQL存儲導入的主數(shù)據(jù),對外通過Restful API提供主數(shù)據(jù)供給服務(wù),它還有一個管理頁面方便管理員維護主數(shù)據(jù)。

TSD引擎與數(shù)據(jù)存儲

TSD引擎負責TSD的寫入和查詢,很多TSD數(shù)據(jù)庫會利用一個成熟的NoSQL數(shù)據(jù)庫進行數(shù)據(jù)存儲,而TSD引擎則專注在TSD數(shù)據(jù)的處理上。這兩部分密不可分,因此我們放在一起討論。

我們對時間序列數(shù)據(jù)庫的選型主要是在目前業(yè)界最主流的兩個產(chǎn)品InfluxDB和OpenTSDB之間展開的。 前者使用GO語言編寫,后端存儲先后使用過LevelDB和BoltDB,現(xiàn)在使用的則是InfluxDB自己實現(xiàn)的Time Structured Merge Tree引擎,OpenTSDB使用Java編寫,后端存儲使用HBase。在單機性能上,多種對比測試顯示InfluxDB具有更高的性能,但我們最終選擇的是OpenTSDB,主要原因是考慮到在集群和水平伸縮方面,背靠HBase的OpenTSDB有明顯的優(yōu)勢,相比之下InfluxDB只在收費的企業(yè)版提供集群功能,同時在集群規(guī)模和支撐的數(shù)據(jù)量上沒有公開詳實的參考數(shù)據(jù),而HBase早已在眾多實際項目特別是國內(nèi)一些知名互聯(lián)網(wǎng)公司中廣泛使用并得到了驗證。另一方面,OpenTSDB和HBase都使用Java編寫,這對于我們整個大數(shù)據(jù)技術(shù)團隊來說在維護和修復一些底層Bug上也相對容易一些。

TSD引擎驅(qū)動

這是一個定制開發(fā)的組件,其作用是對TSD數(shù)據(jù)進行轉(zhuǎn)換和包裹,以便于更好地進行數(shù)據(jù)展示,當數(shù)據(jù)查詢請求到達時,它會根據(jù)請求的內(nèi)容和時間跨度把請求路由到實時庫或批處理庫,當請求返回時,它同樣會過濾響應(yīng)內(nèi)容,對某些字段和值進行映射和轉(zhuǎn)碼,如前所述,因為時間序列數(shù)據(jù)庫對存儲的TSD有很多形式上的限制,某些數(shù)據(jù)不可以直接存儲,它們在入庫前已經(jīng)做了相應(yīng)的格式化處理,在提取展示時需要進行相應(yīng)的反處理。

TSD引擎驅(qū)動本質(zhì)上是一個Web Service,從某種意義上說,這個Web Service像是TSD引擎的一個反向代理,它能靈活和透明地解決一些定制化需求以及非標準數(shù)據(jù)的適配工作,從而避免對TSD引擎和前端展示進行侵入性的修改。

在技術(shù)選型上,所有支持Web Service的框架都可以勝任這個工作,考慮到我們整個大平臺的技術(shù)堆棧都以sbt-native-packager/Java為主,我們實驗性地選擇了Akka-Http,通過利用Akka-Http的HTTP DSL和sbt-native-packager的模式匹配,我們用很少的代碼就實現(xiàn)了既定目標,效果非常好。

數(shù)據(jù)展示

最后,在數(shù)據(jù)展示上,Grafana是我們最佳的選擇。它是一個專門的時序數(shù)據(jù)展示工具,可以直連OpenTSDB,圖表的制作都是通過拖放完成的,它還有一個異常強大的“模版”機制,可以通過一次設(shè)定生成多張圖表。如果既有插件無法滿足展示需求,團隊還以開發(fā)自定義插件。

綜上所述,整個系統(tǒng)的技術(shù)堆棧如下所示:

 

 

物理架構(gòu)

對于平臺的物理架構(gòu)我們不打算進行過多的介紹,因為Hadoop/Spark集群都大同小異,我們這里要討論的是這個平臺在物理架構(gòu)上的一個顯著的特點,就是我們構(gòu)建了兩個獨立的Hadoop/Spark集群,一個負責流處理,另一個負責批處理,這也是踐行Lambda架構(gòu)在物理層面上的一個自然的結(jié)果,兩個集群的數(shù)據(jù)交互依靠HBase的Replication機制透明地實現(xiàn)。其他的非Hadoop/Spark組件會部署在離散的服務(wù)器上。

 

 

實時處理集群和批處理集群除了分工上的不同,在集群結(jié)構(gòu)和節(jié)點配置上也有很大的區(qū)別,特別是在計算資源和存儲資源的分配上。通常,Hadoop集群的計算服務(wù)和存儲服務(wù)是共生在一起的,即HDFS的DataNode和YARN的NodeManager總是collocate的, 這樣做的目的是讓分布式計算盡可能地從本地讀取數(shù)據(jù)進行處理,減少網(wǎng)絡(luò)IO,提升性能。我們的批處理集群就是按這樣的模式進行資源配置的:基于Spark的批處理程序跑在Yarn的NodeManager上,盡量讀寫本地DataNode上的數(shù)據(jù),對于HBase也是同樣的邏輯,讓NodeManager也與DataNode共生在一起。

 

 

在實時處理集群上情況則大不相同。首先,在流處理過程中數(shù)據(jù)是不落地的,因此在流計算的節(jié)點上只會分配NodeManager,而不會有DataNode, 到了數(shù)據(jù)存儲環(huán)節(jié)才會讓HBase的NodeManager與DataNode共生。所以說NodeManager和DataNode總是collocate的說法太絕對,一切還是要根據(jù)實際情況靈活處理。

平臺建設(shè)

從前面介紹的技術(shù)架構(gòu)和選型上不難看出這個系統(tǒng)的復雜性,在建設(shè)過程中我們遇到了很多困難,也積累了一些寶貴的經(jīng)驗,限于篇幅,我們選取了一些有價值的話題和大家進行分享。

圍繞主數(shù)據(jù)進行領(lǐng)域建模

“沒有領(lǐng)域模型的設(shè)計都是耍流氓”,這句看似調(diào)侃的話表達的卻是對軟件設(shè)計的一種嚴肅態(tài)度,領(lǐng)域模型在任何類型的系統(tǒng)里都起著核心作用,大數(shù)據(jù)系統(tǒng)也不例外,你可以不去設(shè)計它,但這并不表示它不存在,一個不能如實反映業(yè)務(wù)邏輯的模型注定會導致整個系統(tǒng)的失敗。在我們這個面向時序數(shù)據(jù)的大數(shù)據(jù)平臺上,所有的TSD都出自于或描述了某一類主數(shù)據(jù)的狀態(tài)或行為,或者說它們都是主數(shù)據(jù)所代表的業(yè)務(wù)實體的產(chǎn)物,比如服務(wù)器的Metrics數(shù)據(jù),這是典型的TSD,它們描述的就是業(yè)務(wù)對象:”服務(wù)器”的狀態(tài)。從OO建模的角度來思考這個問題,如果監(jiān)控系統(tǒng)需要建立針對這個服務(wù)器的一整套監(jiān)控和報警規(guī)則,那么所有相應(yīng)的邏輯必然會追加到“服務(wù)器”以及一些和它相關(guān)聯(lián)的實體上,這就是我們所說的“圍繞主數(shù)據(jù)進行領(lǐng)域建模”。

這一點非常重要且有效,因為它是對所有業(yè)務(wù)邏輯的一種自然的梳理和劃分,最能夠反映領(lǐng)域的本來面目,越是復雜的業(yè)務(wù)場景越能體現(xiàn)優(yōu)越性。所有這些思考和傾向性都在引導我們漸漸地向“領(lǐng)域驅(qū)動設(shè)計”(Domain Driven Design)的方向前進,這是一個非常豐富并且具有實際意義的話題,令人感慨的是我們在大數(shù)據(jù)平臺上讓“領(lǐng)域驅(qū)動設(shè)計”再一次煥發(fā)了生機,以領(lǐng)域模型為核心驅(qū)動業(yè)務(wù)處理和數(shù)據(jù)分析是一個非常明智的選擇,盡管這對團隊整體的素質(zhì)有更高的要求,實施難度也更大,但是回饋也是巨大的。

我們有一個生動的實例:在平臺建設(shè)的早期,限于每個數(shù)據(jù)源的格式和處理邏輯上的差異,每個數(shù)據(jù)源都自己的業(yè)務(wù)處理代碼和獨立的業(yè)務(wù)規(guī)則表,這種處理方式非常類似于傳統(tǒng)企業(yè)應(yīng)用架構(gòu)中的“Transaction Script”模式(關(guān)于Transaction Script請參考Martin Fowler的《Patterns of Enterprise Application Architecture》一書的第9章),伴隨著數(shù)據(jù)源的不斷引入,我們發(fā)現(xiàn)應(yīng)用在很多不同數(shù)據(jù)源上的監(jiān)控和報警邏輯都非常類似,并且針對的業(yè)務(wù)對象也都是一樣的,例如不同的數(shù)據(jù)源都會面向某臺服務(wù)器或某個站點產(chǎn)生報警消息,而我們對這些報警消息的處理有著很大的相似性,這促使我們以主數(shù)據(jù)為對象進行了領(lǐng)域建模,把邏輯進行了統(tǒng)一梳理,在不一致的地方運用適配器、修飾器和策略等模式進行對接,最終將原來離散的代碼和配置統(tǒng)一在了一個領(lǐng)域模型上,大大簡化了編程和維護成本,在處理新加入的數(shù)據(jù)源時變得更加簡便快捷。

最后,補充一點認識,在傳統(tǒng)企業(yè)級應(yīng)用里進行領(lǐng)域驅(qū)動設(shè)計有諸多的困難,其中一個比較突出的問題就是領(lǐng)域?qū)ο蟮某志没,由于?shù)據(jù)存放在關(guān)系型數(shù)據(jù)庫中,領(lǐng)域?qū)ο蟮膶懭牒图虞d都存在一個“對象關(guān)系映射”的問題,盡管有很多成熟的ORM框架能在一定程度上緩解這個問題,但是在傳統(tǒng)企業(yè)級應(yīng)用里落地一個純正的領(lǐng)域模型依然是一個不小的挑戰(zhàn),而大數(shù)據(jù)平臺為領(lǐng)域驅(qū)動設(shè)計提供了一個更加自由的空間,比如大數(shù)據(jù)的計算節(jié)點可以提供足夠的內(nèi)存將領(lǐng)域?qū)ο笠淮涡匀考虞d,免去了ORM中對關(guān)聯(lián)對象加載策略的糾結(jié),而領(lǐng)域?qū)ο髸诖髷?shù)據(jù)處理過程中反復使用,客觀上也需要直接把它們加載到內(nèi)存中使用,再比如,在業(yè)務(wù)處理和分析階段,幾乎所有領(lǐng)域?qū)ο蠖际侵蛔x的,它們只會在同步主數(shù)據(jù)時被更新,這天然地形成了讀寫分離,更加適合CQRS架構(gòu)。

流處理的工程結(jié)構(gòu)

很多團隊在初次使用流計算框架構(gòu)建項目時往往會在如何組織工程結(jié)構(gòu)上感到迷茫,不同于傳統(tǒng)企業(yè)級應(yīng)用經(jīng)過多年積累形成的“套路”,流處理項目的工程結(jié)構(gòu)并沒有一個約定俗成的最佳實踐,我們在這里分享我們的工程結(jié)構(gòu)作為一個參考,希望對你有所啟發(fā)。

 

 

也許你會覺得這個工程結(jié)構(gòu)非常面熟,是的,我們充分借鑒了傳統(tǒng)企業(yè)級應(yīng)用的分層結(jié)構(gòu),每一個色塊都代表著一類組件,映射到工程上就是一個package,讓我們逐一介紹一下:

Stream: 系統(tǒng)中的每一個流都會封裝在一個類中,我們把這些類統(tǒng)一按“XxxStream”形式進行命名,放在stream包里,Stream類里出現(xiàn)的多是與Spark Streaming相關(guān)的API,在涉及實際的業(yè)務(wù)處理時,會調(diào)用相應(yīng)的Service方法,這種設(shè)計反映了我們對流處理的一個基本認識,那就是流計算中的API是一個“門面”(Facade),厚重的業(yè)務(wù)處理不應(yīng)在這些API上直接以Lambda表達式的方式編寫,而應(yīng)該封裝到專門的Service里。這與Web應(yīng)用中Action和Service的關(guān)系極為類似。

Service: 與業(yè)務(wù)相關(guān)的處理邏輯會封裝到Service類里,這是很傳統(tǒng)的做法,但是由于我們深度地應(yīng)用了領(lǐng)域驅(qū)動設(shè)計,所以絕大部分的業(yè)務(wù)邏輯已經(jīng)自然地委派到了領(lǐng)域?qū)ο蟮姆椒ㄉ狭,因此Service也變成了很薄的一層封裝。有個值得一提的細節(jié),我們把所有的Service都做成了object(sbt-native-packager中的object對象),也就是單態(tài), 這樣做的主要的動機是讓所有的Executor節(jié)點在本地加載全局唯一的Service實例,避免Service實例從Driver端到Executor端做無謂的序列化與反序列化操作。

Repository:在相對簡單的系統(tǒng)里,你可以利用Repository直接讀取存放于數(shù)據(jù)庫中的主數(shù)據(jù)和配置信息,如果你的平臺有多處組件都需要使用主數(shù)據(jù),我們建議你務(wù)必建立統(tǒng)一的主數(shù)據(jù)和配置信息讀寫組件,如果是這樣,則專屬于流處理的Repository將不復存在。

Domain:領(lǐng)域模型涉及的實體和值對象都會放在這個包里,業(yè)務(wù)處理和分析的邏輯會按照面向?qū)ο蟮脑O(shè)計理念分散到領(lǐng)域?qū)ο蟮臉I(yè)務(wù)方法上。同樣的,如果建立了統(tǒng)一的主數(shù)據(jù)和配置信息的讀寫組件,則Domain也將不復存在

DTO: 流處理中的DTO并不是為傳輸領(lǐng)域?qū)ο蠖O(shè)計的,它是外部采集的原生數(shù)據(jù)經(jīng)過結(jié)構(gòu)化處理之后在流上的數(shù)據(jù)對象。

項目構(gòu)建:Sbt vs. Maven

由于我們的平臺技術(shù)堆棧以Spark為核心,我們的幾個核心組件都是使用scala編寫的,在項目構(gòu)建上也積累了一些寶貴的經(jīng)驗,早期我們使用的是scala的默認構(gòu)建工具sbt, 作為新一代的構(gòu)建工具,sbt吸收了眾多前輩的優(yōu)點,簡單易用,能夠滿足基本的應(yīng)用場景,但在實際的項目構(gòu)建中,當面臨一些相對復雜的場景時,年青的sbt會顯得比較無力,其中最為我們不能接受的是面向多環(huán)境的構(gòu)建。盡管社區(qū)提出過一些解決方案,例如http://stackoverflow.com/questions/17193795/how-to-add-environment-profile-config-to-sbt , 但是這個方案的缺陷在于對于每一套環(huán)境都要提供全套的配置,即使它們在多數(shù)據(jù)環(huán)境中的值是一樣的。實際上這個問題的本質(zhì)原因是sbt尚沒有類似Maven那樣在構(gòu)建時基于某個配置文件對一些變量進行過濾和替換的Resource+Profile功能,這是很重要的一個需求。

在打包方面,我指的是構(gòu)建一個包含命令行工具、配置文件和各種lib的安裝包,sbt的sbt-native-packager確實非常強大,令人印象深刻。同樣,在面向不同環(huán)境的前提下,打包不同用途的package時,sbt-native-packager的靈活性還有待檢驗。例如,基于我們過去的最佳實踐,面向每一種環(huán)境,我們嘗嘗會利用sbt-native-packager構(gòu)建兩種package,一種是包含全部產(chǎn)出物的標準部署包,一種是僅僅包含每次構(gòu)建都有可能發(fā)生變化的文件,例如項目自身的jar包和一些配置文件,我們把這種包稱為最小化的package,這種package會用于日常持續(xù)集成的部署,它的體積很小,在網(wǎng)絡(luò)帶寬有限的環(huán)境里,它會大大節(jié)約部署時間。

回到Maven,在過去數(shù)年的開發(fā)工作中,Maven滿足了我們各式各樣的構(gòu)建需求,從沒有讓我們失望過,它的約定大于配置的思想和豐富的周邊插件真正實踐了:”Make simple things simple, complex things possible!”從實際效果看,使用Maven構(gòu)建sbt-native-packager項目沒有任何障礙,它成熟而強大的各項功能可以解決實際項目上各式各樣的需求,這一切讓我們最終回歸了Maven。

但是這并不代表我們會在Maven上停滯不前,實際上我們對sbt依然抱有期望,只是它需要時間變得更加強大。在未來某個合適的時機,我想我們會遷移到sbt。

數(shù)據(jù)采集的痛點和應(yīng)對策略

數(shù)據(jù)采集往往是大數(shù)據(jù)平臺上的臟活、累活,除了解決技術(shù)上的問題,團隊還需要進行大量協(xié)調(diào)和溝通工作,因為外部數(shù)據(jù)源都由其他團隊管理,需要從更高的組織層面進行疏通,并且很多數(shù)據(jù)源需要同時為多個外部系統(tǒng)供給數(shù)據(jù),為了確保數(shù)據(jù)源的可用性,會對外部的數(shù)據(jù)采集作業(yè)進行控制,比如限制采集頻率等。我們下面會討論兩個棘手的問題,并分享我們的解決方案。

數(shù)據(jù)采集作業(yè)超時

在我們采集的外部數(shù)據(jù)源中,有一個數(shù)據(jù)庫在某些時刻因為需要同時處理多個外圍系統(tǒng)疊加的查詢請求而經(jīng)常響應(yīng)緩慢,進而導致了我們的數(shù)據(jù)采集作業(yè)超時,而這個Job原來的設(shè)計是每分鐘執(zhí)行一次,每次執(zhí)行時會從目標數(shù)據(jù)庫中查詢最近1分鐘內(nèi)的數(shù)據(jù),這個查詢請求通常在1秒以內(nèi)就可以返回,但是當數(shù)據(jù)庫響應(yīng)緩慢時,一個Job的耗時往往要超過1分鐘,而后續(xù)啟動的Job仍然按啟動時的時間點向前1分鐘作為時間窗口進行查詢,這就出現(xiàn)了數(shù)據(jù)丟失。

應(yīng)對這個問題的一個簡單方案是將Job的執(zhí)行變?yōu)楫惒椒亲枞J剑恳粋Job被觸發(fā)后都在一個獨立的線程中運行。但是這個方案不適用于我們的系統(tǒng),因為這樣采集到的數(shù)據(jù)不能保證時間上的有序性,而這對一個時序數(shù)據(jù)系統(tǒng)至關(guān)重要。所以這一方案被否決。

經(jīng)過仔細的思考,我們認為必須要將這個Job切分成兩個子的Job:第一個Job負責制定周期性的計劃,準確地說是周期性地生成時間窗口參數(shù),第二個Job負責讀取時間窗口參數(shù)執(zhí)行查詢,這一部分的工作并不是周期性的,原則上,只要有時間參數(shù)生成就應(yīng)該立即執(zhí)行,如果執(zhí)行超時,在超時期間,我們需要緩存第一個Job生成的時間參數(shù),而當所有的查詢都及時完成沒有待執(zhí)行的查詢計劃時,第二個Job需要等待新的查詢參數(shù)到達,是的,這實際上是一個生產(chǎn)者-消費者模型,只是生產(chǎn)者是在“有節(jié)奏”地生產(chǎn),在這個模式里,第三個參與者:倉庫,或者說傳送帶,起到了關(guān)鍵的調(diào)節(jié)作用,而一個現(xiàn)成的實現(xiàn)就是JDK自帶的BlockingQueue!于是我們的落地方案是:

第一個Job由定時器周期性觸發(fā),每次觸發(fā)時會把當前時間放到一個BlockingQueue的隊尾。

第二個Job循環(huán)執(zhí)行,每次執(zhí)行的工作就是從BlockingQueue的隊頭取出時間參數(shù),組裝SQL并執(zhí)行。當隊列為空時,由BlockingQueue來阻塞當前線程,等待時間參數(shù)進入隊列。

當?shù)诙䝼Job執(zhí)行完一次時,如果隊列中還有時間參數(shù),會繼續(xù)執(zhí)行步驟2,發(fā)生此類情況時就說明前一次的執(zhí)行超過了1分鐘。

數(shù)據(jù)延遲就緒

我們一直為降低平臺的數(shù)據(jù)延遲做著各種努力,但最讓人感到無力的是外部數(shù)據(jù)源本身在數(shù)據(jù)寫入時發(fā)生了延遲。舉個例子,還是前面提到的數(shù)據(jù)庫,每次采集數(shù)據(jù)設(shè)定的時間區(qū)間是從當前時間到前一分鐘,假定當前時間是00:10,則執(zhí)行的SQL中時間窗口參數(shù)是(00:09,00:10],此時你可能會查詢到1000條數(shù)據(jù),但如果你在00:11以同樣的參數(shù)(00:09,00:10]再次執(zhí)行這條SQL, 返回的數(shù)據(jù)條目就可能變成了1200條,這說明數(shù)據(jù)庫中的數(shù)據(jù)從它在業(yè)務(wù)系統(tǒng)中生成到最后寫入數(shù)據(jù)庫的過程中發(fā)生了延遲,造成這種情況的原因有很多,比如系統(tǒng)存在性能問題等等,總之現(xiàn)狀就是:數(shù)據(jù)就緒發(fā)生了延遲,而對于數(shù)據(jù)采集方這完全不可控。

面對這種問題,我們的應(yīng)對策略是:如果數(shù)據(jù)及時地就緒了,我們要保證能及時的捕獲,如果數(shù)據(jù)延遲就緒,我們要保證至少不會丟掉它;谶@樣的考慮,我們把同一個數(shù)據(jù)源的數(shù)據(jù)采集分成了兩到三個“波次”進行,第一波次的采集緊緊貼近當前時間,并且保持極高的頻率,這一波次是要保證最早最快地采集到當前的新生數(shù)據(jù),第二波次采集的是過去某個時間區(qū)間上的數(shù)據(jù),時間偏移可能在十幾秒到幾分鐘不等,這取決于目標數(shù)據(jù)源的數(shù)據(jù)延遲程度,第二波次是一個明顯的“補償”操作,用于采集在第一波次進行時還未在數(shù)據(jù)庫中就緒的數(shù)據(jù),第三波次則是最后的“托底”操作,它的時間偏移會更大,目的是最后一次補錄數(shù)據(jù),保證數(shù)據(jù)的完整性。

多波次采集的方案會導致出現(xiàn)重復數(shù)據(jù),因此需要進行去重操作,我們把這個工作交給了流處理組件,利用Spark Streaming的checkpoint機制,我們會在流上cache住近一段時間內(nèi)的數(shù)據(jù)作為去重時的比對數(shù)據(jù),當超過設(shè)定的TTL(Time-To-Live)時,數(shù)據(jù)會從流上移除。

作者:bluishglc

來源:CSDN

原文:https://blog.csdn.net/bluishglc/article/details/79277455?utm_source=copy

標簽: Mysql 大數(shù)據(jù) 大數(shù)據(jù)處理 大數(shù)據(jù)技術(shù) 大數(shù)據(jù)平臺 大數(shù)據(jù)系統(tǒng) 代碼 服務(wù)器 互聯(lián)網(wǎng) 互聯(lián)網(wǎng)公司 數(shù)據(jù)分析 數(shù)據(jù)庫 網(wǎng)絡(luò) 知名互聯(lián)網(wǎng)公司

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:數(shù)據(jù)可視化專家的七個秘密

下一篇:兩種數(shù)據(jù)科學編程中的思維模式(附代碼)