Twitter廣告平臺實時計費系統(tǒng)的架構(gòu)增強之道,twitter廣告點擊費用Twitter廣告平臺實時計費系統(tǒng)的架構(gòu)增強之道Twitter 是廣告商吸引受眾的一個熱門平臺。當廣告商發(fā)起一個新的廣告活動,它們會限定一個廣告預(yù)算。Twitter 的廣告服務(wù)器會檢查廣告活動的預(yù)算,以便確定是否還能繼續(xù)投放廣告。如果沒有這個檢......
Twitter 是廣告商吸引受眾的一個熱門平臺。當廣告商發(fā)起一個新的廣告活動,它們會限定一個廣告預(yù)算。Twitter 的廣告服務(wù)器會檢查廣告活動的預(yù)算,以便確定是否還能繼續(xù)投放廣告。如果沒有這個檢查機制,我們可能會在廣告活動達到預(yù)算限額后繼續(xù)提供廣告服務(wù)。我們把這種情況叫作超支。超支會導(dǎo)致 Twitter 的收入損失(由于機會成本的增加——例如,我們本可以在那個位置顯示其他廣告)。所以,我們要建立一個可靠的系統(tǒng)來防止發(fā)生超支。
在深入研究超支是如何發(fā)生前,先來了解一下我們的廣告系統(tǒng)是如何提供廣告服務(wù)的。下面是我們廣告服務(wù)管道的高級架構(gòu)圖:
支出緩存(Spend Cache)——一個分布式緩存服務(wù),可以跟蹤每個廣告活動的當前預(yù)算支出。
實時廣告支出計數(shù)器(Live Spend Counter,LSC)——一個基于 Apache Heron 的服務(wù),負責聚合廣告活動并更新支出緩存。
廣告回調(diào)(Ads Callback)——處理用戶瀏覽事件的管道,為事件添加上下文信息,并將它們發(fā)國際快遞 LSC。
廣告服務(wù)器(Ad Server)——在處理請求時,決定是否應(yīng)該從廣告支出緩存中獲取當前活動的支出。需要注意的是,這里所說的廣告服務(wù)器包括了向用戶提供廣告的多種服務(wù)。
當用戶在 Twitter 上瀏覽廣告時,我們會向廣告回調(diào)管道發(fā)快遞一個事件。一旦活動支出計數(shù)器收到這個事件,它將計算活動的總支出,并在支出緩存中更新活動的支出。對于每個傳入的請求,廣告服務(wù)器管道都會查詢支出緩存,以便獲得活動的當前支出,并根據(jù)剩余的預(yù)算確定是否繼續(xù)提供服務(wù)。
因為我們處理的廣告活動的規(guī)模比較大(數(shù)據(jù)中心每秒有數(shù)以百萬計的廣告瀏覽事件),所以延遲或硬件故障隨時都可能在我們的系統(tǒng)中發(fā)生。如果支出緩存沒有更新最新的活動支出,廣告服務(wù)器就會獲取到陳舊的信息,并繼續(xù)為已經(jīng)達到預(yù)算上限的活動提供廣告服務(wù)。我們將永遠無法收取超出廣告預(yù)算的那部分費用,導(dǎo)致 Twitter 的收入損失。
例如,假設(shè)有一個每天預(yù)算為 100 美元的廣告活動,每一次點擊的價格為 0.01 美元。在沒有超支的情況下,這將為活動創(chuàng)造每天 10000 次點擊的機會。
假設(shè)廣告回調(diào)管道或 LSC 出現(xiàn)故障,導(dǎo)致支出緩存沒有更新,丟失了價值 10 美元的事件,支出緩存只會報告支出為 90 美元,而實際上活動已經(jīng)支出了 100 美元,那么該活動將獲得額外的 1000 次免費點擊機會。
Twitter 有多個數(shù)據(jù)中心,每個數(shù)據(jù)中心都部署了整個廣告服務(wù)管道的副本,包括廣告回調(diào)管道、實時支出計數(shù)器和支出緩存。當用戶點擊廣告時,回調(diào)事件被路由到其中的一個數(shù)據(jù)中心,這個數(shù)據(jù)中心里的回調(diào)管道將負責處理這個事件。
那么,問題就來了:每個數(shù)據(jù)中心計算的總支出只計算該數(shù)據(jù)中心接收到的事件,不包括其他數(shù)據(jù)中心的數(shù)據(jù)。由于廣告客戶的預(yù)算是跨數(shù)據(jù)中心的,這意味著每個數(shù)據(jù)中心的支出信息是不完整的,可能會少算了廣告客戶的實際支出。
為了解決這個問題,我們給回調(diào)事件隊列添加了跨數(shù)據(jù)中心復(fù)制功能,以便讓每個數(shù)據(jù)中心都能夠處理所有的事件。這確保了每個數(shù)據(jù)中心中的支出信息是完整和準確的。
盡管復(fù)制事件為我們帶來了更好的一致性和更準確的支出信息,但系統(tǒng)的容錯能力仍然不是很強。例如,每隔幾周,跨數(shù)據(jù)中心復(fù)制失敗就會導(dǎo)致支出緩存由于事件丟失或滯后而失效。通常,廣告回調(diào)管道會出現(xiàn)系統(tǒng)問題,例如垃圾收集停頓或數(shù)據(jù)中心的不可靠網(wǎng)絡(luò)連接導(dǎo)致的事件處理延遲。由于這些問題發(fā)生在數(shù)據(jù)中心本地,該數(shù)據(jù)中心中的 LSC 接收到的事件與延遲成正比,因此支出緩存的更新也將延遲,從而導(dǎo)致超支。
在過去,如果一個數(shù)據(jù)中心發(fā)生這些故障,我們會禁用這個數(shù)據(jù)中心的 LSC,并讓其他數(shù)據(jù)中心的 LSC 同時更新本地緩存和發(fā)生故障的數(shù)據(jù)中心的 LSC,直到出現(xiàn)滯后的廣告調(diào)管道和 LSC 重新追上來。
這種解決方法有效地避免了臨時性的超支問題,但仍然有幾個不足的地方:
手動切換:啟用跨數(shù)據(jù)中心寫入是一個手動執(zhí)行的過程,需要按一定的順序進行多個設(shè)置更改。我們最終使用了腳本,但仍然需要一個待命工程師手動執(zhí)行腳本。
手動選擇數(shù)據(jù)中心:需要一個包含多個步驟的手動執(zhí)行過程來確定哪個數(shù)據(jù)中心是健康的以及啟用跨數(shù)據(jù)中心寫入是否安全。當故障恢復(fù)需要回到初始配置時,必須重復(fù)類似的過程。有時候,這個過程需要來自不同團隊的多個待命工程師共同努力。
高運維成本:由于管理工作區(qū)涉及了多個手動步驟,回調(diào)基礎(chǔ)設(shè)施問題會帶來很高的運維成本。
由于這種架構(gòu)存在很多問題,我們重新設(shè)計了管道,讓它能更有彈性地應(yīng)對故障,并減少運維人員的干預(yù)。這個解決方案有兩個主要組成部分:
跨數(shù)據(jù)中心寫入:LSC 總是同時更新“備用”數(shù)據(jù)中心的支出緩存和本地緩存。它還會寫入一些有關(guān)數(shù)據(jù)運行狀況的元數(shù)據(jù)。每個 LSC 實例維護兩個單獨的數(shù)據(jù)集,一個只計算本地的信息,另一個只計算來自遠程實例寫入的數(shù)據(jù)。
數(shù)據(jù)集健康檢查:在處理請求時,廣告服務(wù)器管道讀取兩個版本的數(shù)據(jù),并根據(jù)哪個數(shù)據(jù)集更健康自動選擇使用哪個版本。
在正常情況下,新解決方案的工作原理與之前的設(shè)計完全一致。但是,如果本地支出緩存落后了,廣告服務(wù)器能夠檢測到,并自動切換到包含來自遠程寫入數(shù)據(jù)的數(shù)據(jù)集。當本地的問題解決之后,廣告服務(wù)器將自動切換回本地數(shù)據(jù)集。
我們通過常見的故障場景來決定數(shù)據(jù)集的健康情況:
延遲:當廣告回調(diào)管道/LSC 無法及時處理大量的事件,就會出現(xiàn)延遲。事件是按照它們到達的順序處理的,所以我們更傾向于選擇包含最新事件的數(shù)據(jù)集。
丟失事件:在某些故障場景中,事件可能會完全丟失掉。例如,如果廣告回調(diào)管道的跨數(shù)據(jù)中心復(fù)制失敗,其中一個數(shù)據(jù)中心將丟失一些遠程事件。因為所有的數(shù)據(jù)中心都應(yīng)該處理所有的事件,所以我們應(yīng)該選擇處理了最多事件的那個數(shù)據(jù)集。
為了構(gòu)建一個包含這兩個因素的健康檢查機制,我們引入了支出直方圖的概念。
假設(shè)我們有一個滾動窗口,顯示每個數(shù)據(jù)中心的 LSC 在任意給定時刻正在處理的事件計數(shù)。滾動窗口包含最近 60 秒內(nèi)每毫秒處理了多少事件的計數(shù)。當?shù)竭_窗口的末尾,我們刪除頭部的計數(shù),并計算后面 1 毫秒的計數(shù)。我們可以看到 LSC 在 60 秒內(nèi)處理的“事件計數(shù)”的直方圖。直方圖如下圖所示:
為了能夠選擇最佳的數(shù)據(jù)集(在廣告服務(wù)端),我們利用了這個直方圖和最近的事件時間戳。LSC 將這些元數(shù)據(jù)與支出數(shù)據(jù)一起寫入支出緩存。
LSC 在寫入時不會序列化/反序列化整個直方圖。在寫入之前,它會匯總窗口中所有計數(shù)器的計數(shù),并寫入一個聚合值。這里使用事件的近似值就足夠了,近似值可以作為這個數(shù)據(jù)中心的 LSC 總體健康狀況的信號。這是由故障的本質(zhì)決定的——如果故障足夠嚴重,我們將立即看到故障的影響,計數(shù)會顯著下降。如果不是很嚴重的話,數(shù)量幾乎是一樣的。
包含元數(shù)據(jù)的結(jié)構(gòu)體是這樣的:
structSpendHistogram{i64approximateCount;i64timestampMilliSecs;}復(fù)制代碼
在處理請求時,廣告服務(wù)器同時讀取本地和遠程的數(shù)據(jù)集。它使用 SpendHistogram 根據(jù)下面描述的數(shù)據(jù)中心選擇邏輯來決定使用哪個數(shù)據(jù)集作為事實數(shù)據(jù)來源。
選擇數(shù)據(jù)集的邏輯如下:
· 從兩個數(shù)據(jù)中心獲取 SpendHistogram。
· 首選具有最新時間戳和最高事件計數(shù)的數(shù)據(jù)集。
· 如果它們非常相近且都處于正常狀態(tài),就首選本地數(shù)據(jù)集,這樣可以避免由于小的延遲而在兩個數(shù)據(jù)中心之間來回切換。
這可以總結(jié)成以下的真值表:
x = LocalTimeStamp RemoteTimeStamp
y = LocalApproxCount RemoteApproxCount
ts = ThresholdTimeStamp
tc = ThresholdApproxCountPercent
在切換到使用來自遠程數(shù)據(jù)中心的數(shù)據(jù)集之前,我們使用 ts 和 tc 來確定容忍度閾值。如果差值在閾值內(nèi),我們會更傾向于使用本地數(shù)據(jù)集。我們嘗試找到閾值,以便在不需要進行數(shù)據(jù)中心切換的情況下盡早檢測故障。廣告服務(wù)器在處理每個請求時都會發(fā)生這個選擇過程,因此我們會在本地進行緩存,每隔幾秒刷新一次,以防止頻繁的網(wǎng)絡(luò)訪問影響整體性能。
下面是切換使用數(shù)據(jù)中心數(shù)據(jù)的可視化表示。當 DC1 的 LSC 發(fā)生故障時,會導(dǎo)致 DC1 的廣告服務(wù)器自動選擇使用 DC2 的數(shù)據(jù)。
到目前為止,我們討論的方法只涉及兩個數(shù)據(jù)中心。通過引入跨數(shù)據(jù)中心復(fù)制因子的概念,我們可以將設(shè)計擴展到“N”個數(shù)據(jù)中心。復(fù)制因子控制每個 LSC 服務(wù)寫入的遠程數(shù)據(jù)中心的數(shù)量。在讀取數(shù)據(jù)時,我們使用了相同的邏輯,并做了一些優(yōu)化,比如一次讀取(批讀取)所有必要數(shù)據(jù),而不是分多次讀取。
例如,假設(shè) ReplicationFactor 設(shè)置為 2,DC1 中的 LSC 將寫入到 DC1、DC2 和 DC3 的支出緩存,DC2 中的 LSC 將寫入到 DC2、DC3 和 DC4 的支出緩存,DC3 中的 LSC 將寫入到 DC3、DC4 和 DC1 的支出緩存。下圖顯示了三個數(shù)據(jù)中心的復(fù)制原理圖。在每個數(shù)據(jù)中心中,廣告服務(wù)器將讀取三個支出直方圖,并從所有這些數(shù)據(jù)中心選擇首選的數(shù)據(jù)集。根據(jù)我們的網(wǎng)絡(luò)和存儲約束,我們選擇 2 作為復(fù)制因子。
在推出這些變更之后,我們注意到團隊的運維成本發(fā)生了重大變化。之前每個季度由于系統(tǒng)問題會導(dǎo)致多次超支事件,而在過去的一年,都沒有發(fā)生此類事件。這節(jié)省了大量的工程時間,并避免了由于基礎(chǔ)設(shè)施問題而向廣告商發(fā)放補償。
通過識別系統(tǒng)健康關(guān)鍵指標,設(shè)計出最簡單的工程解決方案,并根據(jù)這些指標自動采取行動,我們解決了一個影響服務(wù)管道正確性的關(guān)鍵性問題。我們不僅構(gòu)建了一個具有容錯能力和彈性的系統(tǒng),而且釋放了工程資源,把它們用在更有價值的地方。
特別聲明:以上文章內(nèi)容僅代表作者本人觀點,不代表ESG跨境電商觀點或立場。如有關(guān)于作品內(nèi)容、版權(quán)或其它問題請于作品發(fā)表后的30日內(nèi)與ESG跨境電商聯(lián)系。
二維碼加載中...
使用微信掃一掃登錄
使用賬號密碼登錄
平臺顧問
微信掃一掃
馬上聯(lián)系在線顧問
小程序
ESG跨境小程序
手機入駐更便捷
返回頂部