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

攜程實時用戶行為系統(tǒng)實踐

2018-10-22    來源:編程學(xué)習(xí)網(wǎng)

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

攜程實時用戶行為服務(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)方便擴(kuò)容應(yīng)對流量洪峰的需求等。

而近幾年旅游市場高速增長,數(shù)據(jù)量越來越大,并且會持續(xù)快速增長。有越來越多的使用需求,對系統(tǒng)的實時性,穩(wěn)定性也提出了更高的要求?偟膩碚f,當(dāng)前需求對系統(tǒng)的實時性/可用性/性能/擴(kuò)展性方面都有很高的要求。

一、架構(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)落地,并且有比較好的運(yùn)維支持環(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è)計能夠有不錯的水平擴(kuò)展能力。

目前系統(tǒng)每天處理20億左右的數(shù)據(jù)量,數(shù)據(jù)從上線到可用的時間在300毫秒左右。查詢服務(wù)每天服務(wù)8000萬左右的請求,平均延遲在6毫秒左右。下面從實時性/可用性/性能/部署幾個維度來說明系統(tǒng)的設(shè)計。

二、實時性

作為一個實時系統(tǒng),實時性是首要指標(biāo)。線上系統(tǒng)面對著各種異常情況。例如如下幾種情況:

  1. 突發(fā)流量洪峰,怎么應(yīng)對;

  2. 出現(xiàn)失敗數(shù)據(jù)或故障模塊,如何保證失敗數(shù)據(jù)重試并同時保證新數(shù)據(jù)的處理;

  3. 環(huán)境問題或bug導(dǎo)致數(shù)據(jù)積壓,如何快速消解;

  4. 程序bug,舊數(shù)據(jù)需要重新處理,如何快速處理同時保證新數(shù)據(jù);

系統(tǒng)從設(shè)計之初就考慮了上述情況。

首先是用storm解決了突發(fā)流量洪峰的問題。storm具有如下特性:

圖2:Storm特性

作為一個流計算框架,和早期大數(shù)據(jù)處理的批處理框架有明顯區(qū)別。批處理框架是執(zhí)行完一次任務(wù)就結(jié)束運(yùn)行,而流處理框架則持續(xù)運(yùn)行,理論上永不停止,并且處理粒度是消息級別,因此只要系統(tǒng)的計算能力足夠,就能保證每條消息都能第一時間被發(fā)現(xiàn)并處理。

對當(dāng)前系統(tǒng)來說,通過storm處理框架,消息能在進(jìn)入kafka之后毫秒級別被處理。此外,storm具有強(qiáng)大的scale out能力。只要通過后臺修改worker數(shù)量參數(shù),并重啟topology(storm的任務(wù)名稱),可以馬上擴(kuò)展計算能力,方便應(yīng)對突發(fā)的流量洪峰。

對消息的處理storm支持多種數(shù)據(jù)保證策略,at least once,at most once,exactly once。對實時用戶行為來說,首先是保證數(shù)據(jù)盡可能少丟失,另外要支持包括重試和降級的多種數(shù)據(jù)處理策略,并不能發(fā)揮exactly once的優(yōu)勢,反而會因為事務(wù)支持降低性能,所以實時用戶行為系統(tǒng)采用的atleast once的策略。這種策略下消息可能會重發(fā),所以程序處理實現(xiàn)了冪等支持。

storm 的發(fā)布比較簡單,上傳更新程序jar包并重啟任務(wù)即可完成一次發(fā)布,遺憾的是沒有多版本灰度發(fā)布的支持。

圖3:Storm架構(gòu)

在部分情況下數(shù)據(jù)處理需要重試,比如數(shù)據(jù)庫連接超時,或者無法連接。連接超時可能馬上重試就能恢復(fù),但是無法連接一般需要更長時間等待網(wǎng)絡(luò)或數(shù)據(jù)庫的恢復(fù),這種情況下處理程序不能一直等待,否則會造成數(shù)據(jù)延遲。實時用戶行為系統(tǒng)采用了雙隊列的設(shè)計來解決這個問題。

圖4:雙隊列設(shè)計

生產(chǎn)者將行為紀(jì)錄寫入Queue1(主要保持?jǐn)?shù)據(jù)新鮮),Worker從Queue1消費(fèi)新鮮數(shù)據(jù)。如果發(fā)生上述異常數(shù)據(jù),則Worker將異常數(shù)據(jù)寫入Queue2(主要保持異常數(shù)據(jù))。

這樣Worker對Queue1的消費(fèi)進(jìn)度不會被異常數(shù)據(jù)影響,可以保持消費(fèi)新鮮數(shù)據(jù)。RetryWorker會監(jiān)聽Queue2,消費(fèi)異常數(shù)據(jù),如果處理還沒有成功,則按照一定的策略(如下圖)等待或者重新將異常數(shù)據(jù)寫入Queue2。

圖5:補(bǔ)償重試策略

另外,數(shù)據(jù)發(fā)生積壓的情況下,可以調(diào)整Worker的消費(fèi)游標(biāo),從最新的數(shù)據(jù)重新開始消費(fèi),保證最新數(shù)據(jù)得到處理。中間未經(jīng)處理的一段數(shù)據(jù)則啟動backupWorker,指定起止游標(biāo),在消費(fèi)完指定區(qū)間的數(shù)據(jù)之后,backupWorker會自動停止。(如下圖)

圖6:積壓數(shù)據(jù)消解

三、可用性

作為基礎(chǔ)服務(wù),對可用性的要求比一般的服務(wù)要高得多,因為下游依賴的服務(wù)多,一旦出現(xiàn)故障,有可能會引起級聯(lián)反應(yīng)影響大量業(yè)務(wù)。項目從設(shè)計上對以下問題做了處理,保障系統(tǒng)的可用性:

  1. 系統(tǒng)是否有單點?

  2. DB 擴(kuò)容/維護(hù)/故障怎么辦?

  3. Redis 維護(hù)/升級補(bǔ)丁怎么辦?

  4. 服務(wù)萬一掛了如何快速恢復(fù)?如何盡量不影響下游應(yīng)用?

首先是系統(tǒng)層面上做了全棧集群化。kafka和storm本身比較成熟地支持集群化運(yùn)維;web服務(wù)支持了無狀態(tài)處理并且通過負(fù)載均衡實現(xiàn)集群化;Redis和DB方面攜程已經(jīng)支持主備部署,使用過程中如果主機(jī)發(fā)生故障,備機(jī)會自動接管服務(wù);通過全棧集群化保障系統(tǒng)沒有單點。

另外系統(tǒng)在部分模塊不可用時通過降級處理保障整個系統(tǒng)的可用性。先看看正常數(shù)據(jù)處理流程:(如下圖)

圖7:正常數(shù)據(jù)流程

在系統(tǒng)正常狀態(tài)下,storm會從kafka中讀取數(shù)據(jù),分別寫入到redis和mysql中。服務(wù)從redis拉取(取不到時從db補(bǔ)償),輸出給客戶端。DB降級的情況下,數(shù)據(jù)流程也隨之改變(如下圖)

圖8:系統(tǒng)降級-DB

當(dāng)mysql不可用時,通過打開db降級開關(guān),storm會正常寫入redis,但不再往mysql寫入數(shù)據(jù)。數(shù)據(jù)進(jìn)入reids就可以被查詢服務(wù)使用,提供給客戶端。另外storm會把數(shù)據(jù)寫入一份到kafka的retry隊列,在mysql正常服務(wù)之后,通過關(guān)閉db降級開關(guān),storm會消費(fèi)retry隊列中的數(shù)據(jù),從而把數(shù)據(jù)寫入到mysql中。redis和mysql的數(shù)據(jù)在降級期間會有不一致,但系統(tǒng)恢復(fù)正常之后會通過retry保證數(shù)據(jù)最終的一致性。redis的降級處理也類似(如下圖)

圖9:系統(tǒng)降級-Redis

唯一有點不同的是redis的服務(wù)能力要遠(yuǎn)超過mysql。所以在redis降級時系統(tǒng)的吞吐能力是下降的。這時我們會監(jiān)控db壓力,如果發(fā)現(xiàn)mysql壓力較大,會暫時停止數(shù)據(jù)的寫入,降低mysql的壓力,從而保證查詢服務(wù)的穩(wěn)定。

為了降低故障情況下對下游的影響,查詢服務(wù)通過Netflix的Hystrix組件支持了熔斷模式(如下圖)。

圖10:Circuit Breaker Pattern

在該模式下,一旦服務(wù)失敗請求在給定時間內(nèi)超過一個閾值,就會打開熔斷開關(guān)。在開關(guān)開啟情況下,服務(wù)對后續(xù)請求直接返回失敗響應(yīng),不會再讓請求經(jīng)過業(yè)務(wù)模塊處理,從而避免服務(wù)器進(jìn)一步增加壓力引起雪崩,也不會因為響應(yīng)時間延長拖累調(diào)用方。

開關(guān)打開之后會開始計時,timeout后會進(jìn)入Half Open的狀態(tài),在該狀態(tài)下會允許一個請求通過,進(jìn)入業(yè)務(wù)處理模塊,如果能正常返回則關(guān)閉開關(guān),否則繼續(xù)保持開關(guān)打開直到下次timeout。這樣業(yè)務(wù)恢復(fù)之后就能正常服務(wù)請求。

另外,為了防止單個調(diào)用方的非法調(diào)用對服務(wù)的影響,服務(wù)也支持了多個維度限流,包括調(diào)用方AppId/ip限流和服務(wù)限流,接口限流等。

四、性能&擴(kuò)展

由于在線旅游行業(yè)近幾年的高速增長,攜程作為行業(yè)領(lǐng)頭羊也蓬勃發(fā)展,因此訪問量和數(shù)據(jù)量也大幅提升。公司對業(yè)務(wù)的要求是可以支撐10倍容量擴(kuò)展,擴(kuò)展最難的部分在數(shù)據(jù)層,因為涉及到存量數(shù)據(jù)的遷移。

實時用戶行為系統(tǒng)的數(shù)據(jù)層包括Redis和Mysql,Redis因為實現(xiàn)了一致性哈希,擴(kuò)容時只要加機(jī)器,并對分配到新分區(qū)的數(shù)據(jù)作讀補(bǔ)償就可以。

Mysql 方面,我們也做了水平切分作為擴(kuò)展的準(zhǔn)備,分片數(shù)量的選擇考慮為2的n次方,這樣做在擴(kuò)容時有明顯的好處。因為攜程的mysql數(shù)據(jù)庫現(xiàn)在普遍采用的是一主一備的方式,在擴(kuò)容時可以直接把備機(jī)拉平成第二臺(組)主機(jī)。假設(shè)原來分了2個庫,d0和d1,都放在服務(wù)器s0上,s0同時有備機(jī)s1。擴(kuò)容只需要如下幾步:

  1. 確保s0 -> s1同步順利,沒有明顯延遲

  2. s0 暫時關(guān)閉讀寫權(quán)限

  3. 確認(rèn)s1已經(jīng)完全同步s0更新

  4. s1 開放讀寫權(quán)限

  5. d1 的dns由s0切換到s1

  6. s0 開放讀寫權(quán)限

遷移過程利用mysql的復(fù)制分發(fā)特性,避免了繁瑣易錯的人工同步過程,大大降低了遷移成本和時間。整個操作過程可以在幾分鐘完成,結(jié)合DB降級的功能,只有在dns切換的幾秒鐘時間會產(chǎn)生異常。

整個過程比較簡單方便,降低了運(yùn)維負(fù)擔(dān),一定程度也能降低過多操作造成類似gitlab式悲劇的可能性。

五、部署

前文提到storm部署是比較方便的,只要上傳重啟就可以完成部署。部署之后由于程序重新啟動上下文丟失,可以通過Kafka記錄的游標(biāo)找到之前處理位置,恢復(fù)處理。

另外有部分情況下程序可能需要多版本運(yùn)行,比如行為紀(jì)錄暫時有多個版本,這種情況下我們會新增一個backupJob,在backupJob中運(yùn)行歷史版本。

 

 

來自:http://mp.weixin.qq.com/s/kIwTnNFsNWMcEpEIRZfQlw

 

標(biāo)簽: dns Mysql 大數(shù)據(jù) 大數(shù)據(jù)處理 服務(wù)器 權(quán)限 數(shù)據(jù)庫 網(wǎng)絡(luò)

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

上一篇:說說MQ之RocketMQ(二)

下一篇:服務(wù)端I/O性能大比拼:Node、PHP、Java、Go