攜程實時用戶行為服務(wù)作為基礎(chǔ)服務(wù),目前普遍應(yīng)用在多個場景中,比如猜你喜歡(攜程的推薦系統(tǒng))、動態(tài)廣告、用戶畫像、瀏覽歷史等等。
以猜你喜歡為例,猜你喜歡為應(yīng)用內(nèi)用戶提供潛在選項,提高成交效率。旅行是一項綜合性的需求,用戶往往需要不止一個產(chǎn)品。作為一站式的旅游服務(wù)平臺,跨業(yè)務(wù)線的推薦,特別是實時推薦,能實際滿足用戶的需求,因此在上游提供打通各業(yè)務(wù)線之間的用戶行為數(shù)據(jù)有很大的必要性。
攜程原有的實時用戶行為系統(tǒng)存在一些問題,包括:1)數(shù)據(jù)覆蓋不全;2)數(shù)據(jù)輸出沒有統(tǒng)一格式,對眾多使用方提高了接入成本;3)日志處理模塊是web service,比較難支持多種數(shù)據(jù)處理策略和實現(xiàn)方便擴容應(yīng)對流量洪峰的需求等。
而近幾年旅游市場高速增長,數(shù)據(jù)量越來越大,并且會持續(xù)快速增長。有越來越多的使用需求,對系統(tǒng)的實時性,穩(wěn)定性也提出了更高的要求??偟膩碚f,當(dāng)前需求對系統(tǒng)的實時性/可用性/性能/擴展性方面都有很高的要求。
一、架構(gòu)
這樣的背景下,我們按照如下結(jié)構(gòu)重新設(shè)計了系統(tǒng):
圖1:實時用戶行為系統(tǒng)邏輯視圖
新的架構(gòu)下,數(shù)據(jù)有兩種流向,分別是處理流和輸出流。
在處理流,行為日志會從客戶端(App/Online/H5)上傳到服務(wù)端的Collector Service。Collector Service將消息發(fā)送到分布式隊列。數(shù)據(jù)處理模塊由流計算框架完成,從分布式隊列讀出數(shù)據(jù),處理之后把數(shù)據(jù)寫入數(shù)據(jù)層,由分布式緩存和數(shù)據(jù)庫集群組成。
輸出流相對簡單,Web Service的后臺會從數(shù)據(jù)層拉取數(shù)據(jù),并輸出給調(diào)用方,有的是內(nèi)部服務(wù)調(diào)用,比如推薦系統(tǒng),也有的是輸出到前臺,比如瀏覽歷史。系統(tǒng)實現(xiàn)采用的是Java+Kafka+Storm+Redis+MySQL+Tomcat+Spring的技術(shù)棧。
Java:目前公司內(nèi)部Java化的氛圍比較濃厚,并且Java有比較成熟的大數(shù)據(jù)組件 Kafka/Storm:Kafka作為分布式消息隊列已經(jīng)在公司有比較成熟的應(yīng)用,流計算框架Storm也已經(jīng)落地,并且有比較好的運維支持環(huán)境。 Redis: Redis的HA,SortedSet和過期等特性比較好地滿足了系統(tǒng)的需求。 MySQL: 作為基礎(chǔ)系統(tǒng),穩(wěn)定性和性能也是系統(tǒng)的兩大指標(biāo),對比NoSQL的主要選項,比如HBase和ElasticSearch,十億數(shù)據(jù)級別上MySQL在這兩方面有更好的表現(xiàn),并且經(jīng)過設(shè)計能夠有不錯的水平擴展能力。
目前系統(tǒng)每天處理20億左右的數(shù)據(jù)量,數(shù)據(jù)從上線到可用的時間在300毫秒左右。查詢服務(wù)每天服務(wù)8000萬左右的請求,平均延遲在6毫秒左右。下面從實時性/可用性/性能/部署幾個維度來說明系統(tǒng)的設(shè)計。
二、實時性
作為一個實時系統(tǒng),實時性是首要指標(biāo)。線上系統(tǒng)面對著各種異常情況。例如如下幾種情況:
突發(fā)流量洪峰,怎么應(yīng)對; 出現(xiàn)失敗數(shù)據(jù)或故障模塊,如何保證失敗數(shù)據(jù)重試并同時保證新數(shù)據(jù)的處理; 環(huán)境問題或bug導(dǎo)致數(shù)據(jù)積壓,如何快速消解; 程序bug,舊數(shù)據(jù)需要重新處理,如何快速處理同時保證新數(shù)據(jù);
系統(tǒng)從設(shè)計之初就考慮了上述情況。
首先是用storm解決了突發(fā)流量洪峰的問題。storm具有如下特性:
圖2:Storm特性
作為一個流計算框架,和早期大數(shù)據(jù)處理的批處理框架有明顯區(qū)別。批處理框架是執(zhí)行完一次任務(wù)就結(jié)束運行,而流處理框架則持續(xù)運行,理論上永不停止,并且處理粒度是消息級別,因此只要系統(tǒng)的計算能力足夠,就能保證每條消息都能第一時間被發(fā)現(xiàn)并處理。
對當(dāng)前系統(tǒng)來說,通過storm處理框架,消息能在進入kafka之后毫秒級別被處理。此外,storm具有強大的scale out能力。只要通過后臺修改worker數(shù)量參數(shù),并重啟topology(storm的任務(wù)名稱),可以馬上擴展計算能力,方便應(yīng)對突發(fā)的流量洪峰。
對消息的處理storm支持多種數(shù)據(jù)保證策略,at least>
圖3:Storm架構(gòu)
在部分情況下數(shù)據(jù)處理需要重試,比如數(shù)據(jù)庫連接超時,或者無法連接。連接超時可能馬上重試就能恢復(fù),但是無法連接一般需要更長時間等待網(wǎng)絡(luò)或數(shù)據(jù)庫的恢復(fù),這種情況下處理程序不能一直等待,否則會造成數(shù)據(jù)延遲。實時用戶行為系統(tǒng)采用了雙隊列的設(shè)計來解決這個問題。