互聯網流量下的分層實驗平台是咋做的


前言

對於現在擁有大流量的互聯網平台來說,一個微小的頁面改版或者是一個微小的后台內容推薦模型參數的修改都會產生非常大的影響,如何安全的在線上流量驗證這些改進是否真有助於提高公司的收益或者是用戶的體驗呢?

A/B Test

很容易想到做A/B Test,我們可以用一種方式把全網流量分成100份,取其中兩份流量來進行實驗:一份作為對照組,一份作為實驗組。由於實驗所占流量為全網的1%,故而影響范圍小,即使出現了負收益也不影響大盤。

假設每次請求中都有req_id,我們對req_id取模,然后根據余數來划分流量。在實際工程開發中,通常會對每個實驗產生一個唯一的sample_id作為試驗標識,后端日志記錄該sample_id的相關信息,統計組對離線日志進行統計,對一個實驗下的兩個sample_id(對照組sample_id,實驗組sample_id)的各種統計指標進行對比,來確認試驗效果。如下圖所示:

有兩個實驗:實驗1和實驗n。 每個實驗又分為對照組(基線)和實驗組,每組流量大小相等。 實驗1對照組流量是req_id % 100 = 0,實驗組是req_id % 100 = 1;實驗n對照組流量是req_id % 100 = 98,實驗組是req_id % 100 = 99。只要req_id最后兩位分布夠均勻,那么每份流量大小基本相同。

實驗分層

但是這么做有一個問題,就是最多允許同時進行50個實驗(每個實驗占用兩份流量)。在今天的互聯網企業中,可能同時進行成千上萬的功能開發,而每個功能背后都需要進行實驗,如何盡可能同時滿足這些需求呢?我們對實驗進行分層:即同一份流量可能同時命中兩個或者多個實驗,如下圖所示,一份流量可以同時命中實驗1和實驗n:

但是這么做需要有一個前提,就是兩個層的實驗不能互相沖突,每個層只能修改自己的參數,即如果實驗1和實驗n同時修改參數A,則這兩個實驗必須在同一層,層與層之間的划分就看層間參數是否有交集。

最終我們根據參數來划分層,有依賴關系的參數必須划分在同一層(例如頁面背景顏色和字體顏色必須在同一層,如果頁面背景顏色和字體顏色都被設置成藍色,那么我們就看不到頁面上的字了),沒有依賴關系的參數可以划分在不同層,每個參數只出現在一個層中,不會出現在多層中。

原來每層能做50個實驗,現在把參數分了n層,每層都可以同時進行50個實驗,那么現在可同時進行50 * n 個實驗,n為實驗層數。

流量正交

但是現在還有一個問題,如上圖所示實驗1和實驗n用的是完全相同的流量,這可能會有一些問題:我們雖然確認實驗1和實驗n沒有參數沖突,但是無法確定實驗1和實驗n的實驗效果是否互相影響。比如實驗1進行頁面改版使得頁面更美觀,實驗n對后端推薦模型進行參數優化使得推薦內容更有趣,這兩個實驗不修改相同的參數所以可以分在不同的層中,但是這兩個實驗都會影響用戶頁面停留時長和用戶的點擊率,如果流量完全一樣,我們統計的結果到底是實驗1產生的影響還是實驗n產生的影響呢?我們必須消除這個影響。

  • 流量正交:實驗1的流量必須均勻分布在后一層中,這樣才能保證實驗1觀察的效果主要是由頁面改進帶來的效果,同樣實驗n的流量也必須均勻分布在后一層並且均勻來自於前一層。我們采用哈希值取模代替原始req_id取模,並且哈希時傳入層ID,這樣層與層之間的哈希值不同,從而達到均勻分布。

如下圖所示:

實驗1的流量均勻分布在下一層,實驗n的流量來源均勻分布在前一層

流量划分

大多時候,我們需要保持用戶在產品使用上的體驗一致性,例如:不能前一次看到頁面字體顏色為藍色,刷新一次頁面字體變成綠色。這就提醒我們在進行流量划分的時候,不是所有實驗都能夠用req_id的哈希值進行划分,我們必須使用uid的哈希值進行划分,如果沒有uid我們可以使用cookie的哈希值進行划分。所以,這里面有一個流量優先級划分順序: uid > cookie > req_id。

實驗轉全

當我們在小流量下驗證了一種改進是有效的,那么如何把這個改進在全流量上生效呢?有如兩種方法。

  • 直接修改代碼,使其在全流量上生效。這種方式比較暴力,如果直接在全流量上修改代碼使其生效,那么當遇到一些在大流量下才能發現的問題時,我們不得不重新回滾代碼。
  • 慢慢增大實驗流量,最終使其在全流量上生效。這種方式比較穩妥,即使發生沒有預料到的問題也能通過控制實驗流量來止損,但是它會擠占同一層的其它實驗流量,如果實驗流量增大到100%,那么同一層其它實驗就得不到流量。

我們針對第二種方式對試驗平台進行一個改進,對每一個參數增加一個新的發射層(Launch Layer),如下圖所示:

  • 每個實驗參數可以同時既在發射層,又在實驗層。
  • 實驗層可以覆蓋發射層的參數值。
  • 每個參數最多只能在一個發射層。

當小流量實驗需要全量上線時,實驗進行層間轉移:把實驗從實驗層搬到發射層,通過調節發射層的實驗組與對照組(一般是基線,即線上流量用的參數默認值)比例來使得改進最終用於全流量,這樣既不影響原有的實驗流量分配,又能夠快速調節流量大小。在調節期間,如果發現問題,可以控制發射層實驗組與對照組的流量比例來止損。當我們的改進在發射層上全流量上線后,觀察一段時間沒有什么問題,就可以放心通過修改代碼來把改進應用到線上全流量,並且撤掉發射層。

工程開發與實驗評估

到此為止,我們討論了實驗平台的設計的理論依據,接下來就是工程開發。實驗平台應該在一次訪問的入口處,根據本次請求的相關信息來決定命中哪個實驗並生成一個唯一的sample_id,之后把sample_id傳遞到下游服務;下游各個服務根據sample_id來人為修改代碼,根據sample_id做不同的動作,並且記錄相關日志。

對於一個成熟的實驗平台來說,其應該具備如下幾個功能:

  • 能夠靈活配置試驗流量並快速生效(通常使用配置下發)。
  • 能夠檢查實驗配置合法性。
  • 有一套信服的評估標准體系(由專門的統計組人員進行專業評估)。

結語

以上就是一個實驗平台建設時需要考慮的基本的原理性的東西,希望能對小伙伴有幫助。由於水平有限,文中某些地方講的不合理或者不對,希望小伙伴留言指教。

參考文獻

《Overlapping Expeeriment Infrastructure: More, Better, Faster Experimentation》, Diane Tang, Ashish Agarwal, Deirdre O'Brien, Mike Meyer, Google, Inc.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM