針對上面的幾個情況,我們的架構(gòu)做了調(diào)整,如下圖:
愛奇藝廣告平臺的架構(gòu)設(shè)計(jì)與演進(jìn)之路
對比上線伊始的架構(gòu),此階段架構(gòu)調(diào)整體現(xiàn)在以下幾個方面:
投放服務(wù)性能優(yōu)化 – 包括索引分片和增加粗排序模塊,主要解決了上述流量增長、廣告主數(shù)量訂單增長等方面帶來的性能問題
索引分片是把原來的一份索引拆分成多份,對應(yīng)的一個請求會被拆分成多個子請求并行處理,這樣每個請求的處理時(shí)間會減少,從而有效減少長尾請求數(shù)量。
粗排序:全量召回的好處是收益最大化,缺點(diǎn)是性能會隨著訂單量增加而線性下降;粗排序在召回階段過濾掉沒有競爭力的低價(jià)值的(ECPM 較低的)廣告,低價(jià)值廣告被投放的概率和產(chǎn)生轉(zhuǎn)化的概率很低,因此粗排序的過濾對整體收入影響很小,同時(shí)能有效減少進(jìn)入后續(xù)核心計(jì)算邏輯(包括精排序及其他的業(yè)務(wù)邏輯)的訂單數(shù)量,使得服務(wù)壓力不隨訂單量而線性增長。
計(jì)費(fèi)服務(wù)架構(gòu)優(yōu)化 - 主要是提升系統(tǒng)的可擴(kuò)展性和解決超投問題
可擴(kuò)展性通過服務(wù)拆分來解決,把單一模塊的計(jì)費(fèi)服務(wù)拆分成三個模塊,拆分之后日志收集模塊對外提供服務(wù),主要職責(zé)是接收日志請求并立即返回,保證極低的響應(yīng)時(shí)間;然后對計(jì)費(fèi)日志和非計(jì)費(fèi)日志進(jìn)行不同的處理;檢測過濾模塊主要職責(zé)是進(jìn)行定向檢查和異常日志識別。計(jì)費(fèi)服務(wù)把有效計(jì)費(fèi)數(shù)據(jù)更新到計(jì)費(fèi)系統(tǒng)。拆分成三個模塊之后,每個模塊都很簡單,符合微服務(wù)基本原則之一:單一職責(zé)。
關(guān)于超投, 先看第一個問題:超投不計(jì)費(fèi)。
主要難點(diǎn)在于:
同一個廣告的計(jì)費(fèi)請求是并發(fā)的;
計(jì)費(fèi)系統(tǒng)是分布式的,出于性能考慮,請求的處理流程需要是無鎖的。
我們在計(jì)費(fèi)系統(tǒng)中解決這個問題的思路如下:
首先,要嚴(yán)格準(zhǔn)確地計(jì)費(fèi),就要對并行的請求進(jìn)行串行處理,Redis 的單線程模型天然滿足串行計(jì)費(fèi)的需求,我們決定基于 Redis 來實(shí)現(xiàn)這個架構(gòu),把計(jì)費(fèi)的邏輯以腳本的形式在 Redis 線程中執(zhí)行,避免了先讀后寫的邏輯,這樣兩個根本原因都消除了。
接下來的任務(wù)就是設(shè)計(jì)一個基于 Redis 的高可用高性能的架構(gòu)。我們考慮了兩種可選方案。
方案 1:數(shù)據(jù)分片,架構(gòu)中有多個主 Redis,每個主 Redis 存儲一個分?jǐn)?shù)分片,日志收集服務(wù)處理有效計(jì)費(fèi)請求時(shí)要更新主 Redis;每個主 Redis 都有對應(yīng)的只讀從 Redis,投放服務(wù)根據(jù)分片算法到對應(yīng)的從 Redis 上獲取廣告的實(shí)時(shí)消耗數(shù)據(jù)。
愛奇藝廣告平臺的架構(gòu)設(shè)計(jì)與演進(jìn)之路
該方案的優(yōu)點(diǎn)是可擴(kuò)展性強(qiáng),可以通過擴(kuò)容來解決性能問題;缺點(diǎn)是運(yùn)維復(fù)雜,要滿足高可用系統(tǒng)架構(gòu)還要更復(fù)雜;
上篇:
下篇: