本文是酷狗音樂的架構(gòu)師王勁對酷狗大數(shù)據(jù)架構(gòu)重構(gòu)的總結(jié)。酷狗音樂的大數(shù)據(jù)架構(gòu)本身很經(jīng)典,而這篇講解了對原來的架構(gòu)上進行重構(gòu)的工作內(nèi)容,總共分為重構(gòu)的原因、新一代的大數(shù)據(jù)技術(shù)架構(gòu)、踩過的坑、后續(xù)持續(xù)改進四個部分來給大家談酷狗音樂大數(shù)據(jù)平臺重構(gòu)的過程。
眨眼就是新的一年了,時間過的真快,趁這段時間一直在寫總結(jié)的機會,也總結(jié)下上一年的工作經(jīng)驗,避免重復(fù)踩坑。酷狗音樂大數(shù)據(jù)平臺重構(gòu)整整經(jīng)歷了一年時間,大頭的行為流水?dāng)?shù)據(jù)遷移到新平臺穩(wěn)定運行,在這過程中填過坑,挖過坑,為后續(xù)業(yè)務(wù)的實時計算需求打下了很好的基礎(chǔ)。在此感謝酷狗團隊成員的不懈努力,大部分從開始只知道大數(shù)據(jù)這個概念,到現(xiàn)在成為團隊的技術(shù)支柱,感到很欣慰。
從重構(gòu)原因,技術(shù)架構(gòu),踩過的坑,后續(xù)持續(xù)改進四個方面來描述酷狗音樂大數(shù)據(jù)平臺重構(gòu)的過程,在此拋磚引玉,這次的內(nèi)容與6月份在高可用架構(gòu)群分享的大數(shù)據(jù)技術(shù)實踐的有點不同,技術(shù)架構(gòu)做了些調(diào)整。
其實大數(shù)據(jù)平臺是一個龐大的系統(tǒng)工程,整個建設(shè)周期很長,涉及的生態(tài)鏈很長(包括:數(shù)據(jù)采集、接入,清洗、存儲計算、數(shù)據(jù)挖掘,可視化等環(huán)節(jié),每個環(huán)節(jié)都當(dāng)做一個復(fù)雜的系統(tǒng)來建設(shè)),風(fēng)險也很大。
重構(gòu)原因
在講重構(gòu)原因前,先介紹下原有的大數(shù)據(jù)平臺架構(gòu),如下圖:
從上圖可知,主要基于Hadoop1.x+hive做離線計算(T+1),基于大數(shù)據(jù)平臺的數(shù)據(jù)采集、數(shù)據(jù)接入、數(shù)據(jù)清洗、作業(yè)調(diào)度、平臺監(jiān)控幾個環(huán)節(jié)存在的一些問題來列舉下。
數(shù)據(jù)采集:
數(shù)據(jù)收集接口眾多,且數(shù)據(jù)格式混亂,基本每個業(yè)務(wù)都有自己的上報接口
存在較大的重復(fù)開發(fā)成本
不能匯總上報,消耗客戶端資源,以及網(wǎng)絡(luò)流量
每個接口收集數(shù)據(jù)項和格式不統(tǒng)一,加大后期數(shù)據(jù)統(tǒng)計分析難度
各個接口實現(xiàn)質(zhì)量并不高,存在被刷,泄密等風(fēng)險
數(shù)據(jù)接入:
通過rsync同步文件,很難滿足實時流計算的需求
接入數(shù)據(jù)出現(xiàn)異常后,很難排查及定位問題,需要很高的人力成本排查
業(yè)務(wù)系統(tǒng)數(shù)據(jù)通過Kettle每天全量同步到數(shù)據(jù)中心,同步時間長,導(dǎo)致依賴的作業(yè)經(jīng)常會有延時現(xiàn)象
數(shù)據(jù)清洗:
ETL集中在作業(yè)計算前進行處理
存在重復(fù)清洗
作業(yè)調(diào)度:
大部分作業(yè)通過crontab調(diào)度,作業(yè)多了后不利于管理
經(jīng)常出現(xiàn)作業(yè)調(diào)度沖突
平臺監(jiān)控:
只有硬件與操作系統(tǒng)級監(jiān)控
數(shù)據(jù)平臺方面的監(jiān)控等于空白
基于以上問題,結(jié)合在大數(shù)據(jù)中,數(shù)據(jù)的時效性越高,數(shù)據(jù)越有價值(如:實時個性化推薦系統(tǒng),RTB系統(tǒng),實時預(yù)警系統(tǒng)等)的理念,因此,開始大重構(gòu)數(shù)據(jù)平臺架構(gòu)。
新一代大數(shù)據(jù)技術(shù)架構(gòu)
在講新一代大數(shù)據(jù)技術(shù)架構(gòu)前,先講下大數(shù)據(jù)特征與大數(shù)據(jù)技術(shù)要解決的問題。
1.大數(shù)據(jù)特征:“大量化(Volume)、多樣化(Variety)、快速化(Velocity)、價值密度低(Value)”就是“大數(shù)據(jù)”顯著的4V特征,或者說,只有具備這些特點的數(shù)據(jù),才是大數(shù)據(jù)。
2.大數(shù)據(jù)技術(shù)要解決的問題:大數(shù)據(jù)技術(shù)被設(shè)計用于在成本可承受的條件下,通過非常快速(velocity)地采集、發(fā)現(xiàn)和分析,從大量(volumes)、多類別(variety)的數(shù)據(jù)中提取價值(value),將是IT領(lǐng)域新一代的技術(shù)與架構(gòu)。
介紹了大數(shù)據(jù)的特性及大數(shù)據(jù)技術(shù)要解決的問題,我們先看看新一代大數(shù)據(jù)技術(shù)架構(gòu)的數(shù)據(jù)流架構(gòu)圖:
從這張圖中,可以了解到大數(shù)據(jù)處理過程可以分為數(shù)據(jù)源、數(shù)據(jù)接入、數(shù)據(jù)清洗、數(shù)據(jù)緩存、存儲計算、數(shù)據(jù)服務(wù)、數(shù)據(jù)消費等環(huán)節(jié),每個環(huán)節(jié)都有具有高可用性、可擴展性等特性,都為下一個節(jié)點更好的服務(wù)打下基礎(chǔ)。整個數(shù)據(jù)流過程都被數(shù)據(jù)質(zhì)量監(jiān)控系統(tǒng)監(jiān)控,數(shù)據(jù)異常自動預(yù)警、告警。
新一代大數(shù)據(jù)整體技術(shù)架構(gòu)如圖:
將大數(shù)據(jù)計算分為實時計算與離線計算,在整個集群中,奔著能實時計算的,一定走實時計算流處理,通過實時計算流來提高數(shù)據(jù)的時效性及數(shù)據(jù)價值,同時減輕集群的資源使用率集中現(xiàn)象。
整體架構(gòu)從下往上解釋下每層的作用:
數(shù)據(jù)實時采集:
主要用于數(shù)據(jù)源采集服務(wù),從數(shù)據(jù)流架構(gòu)圖中,可以知道,數(shù)據(jù)源分為前端日志,服務(wù)端日志,業(yè)務(wù)系統(tǒng)數(shù)據(jù)。下面講解數(shù)據(jù)是怎么采集接入的。
a.前端日志采集接入:
前端日志采集要求實時,可靠性,高可用性等特性。技術(shù)選型時,對開源的數(shù)據(jù)采集工具flume,scribe,chukwa測試對比,發(fā)現(xiàn)基本滿足不了我們的業(yè)務(wù)場景需求。所以,選擇基于kafka開發(fā)一套數(shù)據(jù)采集網(wǎng)關(guān),來完成數(shù)據(jù)采集需求。數(shù)據(jù)采集網(wǎng)關(guān)的開發(fā)過程中走了一些彎路,最后采用nginx+lua開發(fā),基于lua實現(xiàn)了kafka生產(chǎn)者協(xié)議。有興趣同學(xué)可以去Github上看看,另一同事實現(xiàn)的,現(xiàn)在在github上比較活躍,被一些互聯(lián)網(wǎng)公司應(yīng)用于線上環(huán)境了。
b.后端日志采集接入:
FileCollect,考慮到很多線上環(huán)境的環(huán)境變量不能改動,為減少侵入式,目前是采用Go語言實現(xiàn)文件采集,年后也準(zhǔn)備重構(gòu)這塊。
前端,服務(wù)端的數(shù)據(jù)采集整體架構(gòu)如下圖:
c.業(yè)務(wù)數(shù)據(jù)接入
利用Canal通過MySQL的binlog機制實時同步業(yè)務(wù)增量數(shù)據(jù)。
數(shù)據(jù)統(tǒng)一接入:為了后面數(shù)據(jù)流環(huán)節(jié)的處理規(guī)范,所有的數(shù)據(jù)接入數(shù)據(jù)中心,必須通過數(shù)據(jù)采集網(wǎng)關(guān)轉(zhuǎn)換統(tǒng)一上報給Kafka集群,避免后端多種接入方式的處理問題。
數(shù)據(jù)實時清洗(ETL):為了減輕存儲計算集群的資源壓力及數(shù)據(jù)可重用性角度考慮,把數(shù)據(jù)解壓、解密、轉(zhuǎn)義,部分簡單的補全,異常數(shù)據(jù)處理等工作前移到數(shù)據(jù)流中處理,為后面環(huán)節(jié)的數(shù)據(jù)重用打下扎實的基礎(chǔ)(實時計算與離線計算)。
數(shù)據(jù)緩存重用:為了避免大量數(shù)據(jù)流(400+億條/天)寫入HDFS,導(dǎo)致HDFS客戶端不穩(wěn)定現(xiàn)象及數(shù)據(jù)實時性考慮,把經(jīng)過數(shù)據(jù)實時清洗后的數(shù)據(jù)重新寫入Kafka并保留一定周期,離線計算(批處理)通過KG-Camus拉到HDFS(通過作業(yè)調(diào)度系統(tǒng)配置相應(yīng)的作業(yè)計劃),實時計算基于Storm/JStorm直接從Kafka消費,有很完美的解決方案storm-kafka組件。
離線計算(批處理):通過spark,spark SQL實現(xiàn),整體性能比hive提高5—10倍,hive腳本都在轉(zhuǎn)換為Spark/Spark SQL;部分復(fù)雜的作業(yè)還是通過Hive/Spark的方式實現(xiàn)。在離線計算中大部分公司都會涉及到數(shù)據(jù)倉庫的問題,酷狗音樂也不例外,也有數(shù)據(jù)倉庫的概念,只是我們在做存儲分層設(shè)計時弱化了數(shù)據(jù)倉庫概念。數(shù)據(jù)存儲分層模型如下圖:
大數(shù)據(jù)平臺數(shù)據(jù)存儲模型分為:數(shù)據(jù)緩沖層Data Cache Layer(DCL)、數(shù)據(jù)明細層Data Detail Layer(DDL)、公共數(shù)據(jù)層(Common)、數(shù)據(jù)匯總層Data Summary Layer(DSL)、數(shù)據(jù)應(yīng)用層Data Application Layer(DAL)、數(shù)據(jù)分析層(Analysis)、臨時提數(shù)層(Temp)。
數(shù)據(jù)緩沖層(DCL):存儲業(yè)務(wù)系統(tǒng)或者客戶端上報的,經(jīng)過解碼、清洗、轉(zhuǎn)換后的原始數(shù)據(jù),為數(shù)據(jù)過濾做準(zhǔn)備。
數(shù)據(jù)明細層(DDL):存儲接口緩沖層數(shù)據(jù)經(jīng)過過濾后的明細數(shù)據(jù)。
公共數(shù)據(jù)層(Common):主要存儲維表數(shù)據(jù)與外部業(yè)務(wù)系統(tǒng)數(shù)據(jù)。
數(shù)據(jù)匯總層(DSL):存儲對明細數(shù)據(jù),按業(yè)務(wù)主題,與公共數(shù)據(jù)層數(shù)據(jù)進行管理后的用戶行為主題數(shù)據(jù)、用戶行為寬表數(shù)據(jù)、輕量匯總數(shù)據(jù)等。為數(shù)據(jù)應(yīng)用層統(tǒng)計計算提供基礎(chǔ)數(shù)據(jù)。數(shù)據(jù)匯總層的數(shù)據(jù)永久保存在集群中。
數(shù)據(jù)應(yīng)用層(DAL):存儲運營分析(Operations Analysis )、指標(biāo)體系(Metrics System)、線上服務(wù)(Online Service)與用戶分析(User Analysis)等。需要對外輸出的數(shù)據(jù)都存儲在這一層。主要基于熱數(shù)據(jù)部分對外提供服務(wù),通過一定周期的數(shù)據(jù)還需要到DSL層裝載查詢。
數(shù)據(jù)分析層(Analysis):存儲對數(shù)據(jù)明細層、公共數(shù)據(jù)層、數(shù)據(jù)匯總層關(guān)聯(lián)后經(jīng)過算法計算的、為推薦、廣告、榜單等數(shù)據(jù)挖掘需求提供中間結(jié)果的數(shù)據(jù)。
臨時提數(shù)層(Temp):存儲臨時提數(shù)、數(shù)據(jù)質(zhì)量校驗等生產(chǎn)的臨時數(shù)據(jù)。
實時計算:基于Storm/JStorm,Drools,Esper。主要應(yīng)用于實時監(jiān)控系統(tǒng)、APM、數(shù)據(jù)實時清洗平臺、實時DAU統(tǒng)計等。
HBase/MySQL:用于實時計算,離線計算結(jié)果存儲服務(wù)。
Redis:用于中間計算結(jié)果存儲或字典數(shù)據(jù)等。
Elasticsearch:用于明細數(shù)據(jù)實時查詢及HBase的二級索引存儲(這塊目前在數(shù)據(jù)中心還沒有大規(guī)模使用,有興趣的同學(xué)可以加入我們一起玩ES)。
Druid:目前用于支持大數(shù)據(jù)集的快速即席查詢(ad-hoc)。
數(shù)據(jù)平臺監(jiān)控系統(tǒng):數(shù)據(jù)平臺監(jiān)控系統(tǒng)包括基礎(chǔ)平臺監(jiān)控系統(tǒng)與數(shù)據(jù)質(zhì)量監(jiān)控系統(tǒng),數(shù)據(jù)平臺監(jiān)控系統(tǒng)分為2大方向,宏觀層面和微觀層面。宏觀角度的理解就是進程級別,拓?fù)浣Y(jié)構(gòu)級別,拿Hadoop舉例,如:DataNode,NameNode,JournalNode,ResourceManager,NodeManager,主要就是這5大組件,通過分析這些節(jié)點上的監(jiān)控數(shù)據(jù),一般你能夠定位到慢節(jié)點,可能某臺機器的網(wǎng)絡(luò)出問題了,或者說某臺機器執(zhí)行的時間總是大于正常機器等等這樣類似的問題。剛剛說的另一個監(jiān)控方向,就是微觀層面,就是細粒度化的監(jiān)控,基于user用戶級別,基于單個job,單個task級別的監(jiān)控,像這類監(jiān)控指標(biāo)就是另一大方向,這類的監(jiān)控指標(biāo)在實際的使用場景中特別重要,一旦你的集群資源是開放給外面的用戶使用,用戶本身不了解你的這套機制原理,很容易會亂申請資源,造成嚴(yán)重拖垮集群整體運作效率的事情,所以這類監(jiān)控的指標(biāo)就是為了防止這樣的事情發(fā)生。目前我們主要實現(xiàn)了宏觀層面的監(jiān)控。如:數(shù)據(jù)質(zhì)量監(jiān)控系統(tǒng)實現(xiàn)方案如下。
大數(shù)據(jù)平臺重構(gòu)過程中踩過的坑
我們在大數(shù)據(jù)平臺重構(gòu)過程中踩過的坑,大致可以分為操作系統(tǒng)、架構(gòu)設(shè)計、開源組件三類,下面主要列舉些比較典型的,花時間比較長的問題。
操作系統(tǒng)級的坑
Hadoop的I/O性能很大程度上依賴于Linux本地文件系統(tǒng)的讀寫性能。Linux中有多種文件系統(tǒng)可供選擇,比如ext3和ext4,不同的文件系統(tǒng)性能有一定的差別。我們主要想利用ext4文件系統(tǒng)的特性,由于之前的操作系統(tǒng)都是CentOS5.9不支持ext4文件格式,所以考慮操作系統(tǒng)升級為CentOS6.3版本,部署Hadoop集群后,作業(yè)一啟動,就出現(xiàn)CPU內(nèi)核過高的問題。如下圖:
經(jīng)過很長時間的測試驗證,發(fā)現(xiàn)CentOS6優(yōu)化了內(nèi)存申請的效率,引入了THP的特性,而Hadoop是高密集型內(nèi)存運算系統(tǒng),這個改動給hadoop帶來了副作用。通過以下內(nèi)核參數(shù)優(yōu)化關(guān)閉系統(tǒng)THP特性,CPU內(nèi)核使用率馬上下降,如下圖:
echo never > /sys/kernel/mm/redhat_transparent_hugepage/enabled
echo never > /sys/kernel/mm/redhat_transparent_hugepage/defrag
2.架構(gòu)設(shè)計的坑
最初的數(shù)據(jù)流架構(gòu)是數(shù)據(jù)采集網(wǎng)關(guān)把數(shù)據(jù)上報給Kafka,再由數(shù)據(jù)實時清洗平臺(ETL)做預(yù)處理后直接實時寫入HDFS,如下圖:
此架構(gòu),需要維持HDFS Client的長連接,由于網(wǎng)絡(luò)等各種原因?qū)е耂torm實時寫入HDFS經(jīng)常不穩(wěn)定,隔三差五的出現(xiàn)數(shù)據(jù)異常,使后面的計算結(jié)果異常不斷,當(dāng)時嘗試過很多種手段去優(yōu)化,如:保證長連接、連接斷后重試機制、調(diào)整HDFS服務(wù)端參數(shù)等,都解決的不是徹底。
每天異常不斷,舊異常沒解決,新異常又來了,在壓力山大的情況下,考慮從架構(gòu)角度調(diào)整,不能只從具體的技術(shù)點去優(yōu)化了,在做架構(gòu)調(diào)整時,考慮到我們架構(gòu)重構(gòu)的初衷,提高數(shù)據(jù)的實時性,盡量讓計算任務(wù)實時化,但重構(gòu)過程中要考慮現(xiàn)有業(yè)務(wù)的過渡,所以架構(gòu)必須支持實時與離線的需求,結(jié)合這些需求,在數(shù)據(jù)實時清洗平臺(ETL)后加了一層數(shù)據(jù)緩存重用層(kafka),也就是經(jīng)過數(shù)據(jù)實時清洗平臺后的數(shù)據(jù)還是寫入kafka集群,由于kafka支持重復(fù)消費,所以同一份數(shù)據(jù)可以既滿足實時計算也滿足離線計算,從上面的整體技術(shù)架構(gòu)也可以看出,如下圖:
KG-Camus組件也是基于架構(gòu)調(diào)整后,重新實現(xiàn)了一套離線消費Kafka集群數(shù)據(jù)的組件,此組件是參考LinkedIn的Camus實現(xiàn)的。此方式,使數(shù)據(jù)消費模式由原來的推方式改為拉模式了,不用維持HDFS Client的長連接等功能了,直接由作業(yè)調(diào)度系統(tǒng)每隔時間去拉一次數(shù)據(jù),不同的業(yè)務(wù)可以設(shè)置不同的時間間隔,從此架構(gòu)調(diào)整上線后,基本沒有類似的異常出現(xiàn)了。
這個坑,是我自己給自己挖的,導(dǎo)致我們的重構(gòu)計劃延期2個月,主要原因是由最初技術(shù)預(yù)研究測試不充分所導(dǎo)致。
3.開源組件的坑
由于整個數(shù)據(jù)平臺涉及到的開源組件很多,踩過的坑也是十個手指數(shù)不過來。
1)、當(dāng)我們的行為數(shù)據(jù)全量接入到Kafka集群(幾百億/天),數(shù)據(jù)采集網(wǎng)卡出現(xiàn)大量連接超時現(xiàn)象,但萬兆網(wǎng)卡進出流量使用率并不是很高,只有幾百Mbit/s,經(jīng)過大量的測試排查后,調(diào)整以下參數(shù),就是順利解決了此問題。調(diào)整參數(shù)后網(wǎng)卡流量如下圖:
a)、num.network.threads(網(wǎng)絡(luò)處理線程數(shù))值應(yīng)該比cpu數(shù)略大
b)、num.io.threads(接收網(wǎng)絡(luò)線程請求并處理線程數(shù))值提高為cpu數(shù)兩倍
2)、在hive0.14 版本中,利用函數(shù)ROW_NUMBER() OVER對數(shù)據(jù)進行數(shù)據(jù)處理后,導(dǎo)致大量的作業(yè)出現(xiàn)延時很大的現(xiàn)象,經(jīng)異常排查后,發(fā)現(xiàn)在數(shù)據(jù)記錄數(shù)沒變的情況,數(shù)據(jù)的存儲容量擴大到原來的5倍左右,導(dǎo)致MapReduce執(zhí)行很慢造成的。改為自己實現(xiàn)類似的函數(shù)后,解決了容量擴大為原來幾倍的現(xiàn)象。說到這里,也在此請教讀到此處的讀者一個問題,在海量數(shù)據(jù)去重中采用什么算法或組件進行比較合適,既能高性能又能高準(zhǔn)確性。
3)、在業(yè)務(wù)實時監(jiān)控系統(tǒng)中,用OpenTSDB與實時計算系統(tǒng)(storm)結(jié)合,用于聚合并存儲實時metric數(shù)據(jù)。在這種實現(xiàn)中,通常需要在實時計算部分使用一個時間窗口(window),用于聚合實時數(shù)據(jù),然后將聚合結(jié)果寫入tsdb。但是,由于在實際情況中,實時數(shù)據(jù)在采集、上報階段可能會存在延時,而導(dǎo)致tsdb寫入的數(shù)據(jù)不準(zhǔn)確。針對這個問題,我們做了一個改進,在原有tsdb寫入api的基礎(chǔ)上,增加了一個原子加的api。這樣,延遲到來的數(shù)據(jù)會被疊加到之前寫入的數(shù)據(jù)之上,實時的準(zhǔn)確性由于不可避免的原因(采集、上報階段)產(chǎn)生了延遲,到最終的準(zhǔn)確性也可以得到保證。另外,添加了這個改進之后,實時計算端的時間窗口就不需要因為考慮延遲問題設(shè)置得比較大,這樣既節(jié)省了內(nèi)存的消耗,也提高了實時性。
后續(xù)持續(xù)改進
數(shù)據(jù)存儲(分布式內(nèi)存文件系統(tǒng)(Tachyon)、數(shù)據(jù)多介質(zhì)分層存儲、數(shù)據(jù)列式存儲)、即席查詢(OLAP)、資源隔離、數(shù)據(jù)安全、平臺微觀層面監(jiān)控、數(shù)據(jù)對外服務(wù)等。
作者介紹:王勁:目前就職酷狗音樂,大數(shù)據(jù)架構(gòu)師,負(fù)責(zé)酷狗大數(shù)據(jù)技術(shù)規(guī)劃、建設(shè)、應(yīng)用。 11年的IT從業(yè)經(jīng)驗,2年分布式應(yīng)用開發(fā),3年大數(shù)據(jù)技術(shù)實踐經(jīng)驗,主要研究方向流式計算、大數(shù)據(jù)存儲計算、分布式存儲系統(tǒng)、NoSQL、搜索引擎等。