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