遊戲中的abtest功能實現,演進與覆盤

前言

abtest是一種很常見的,利用真實用戶來測試的方法。在遊戲中,可以用abtest來測試不同的活動,不同的商品,不同的定價,不同的匹配策略等等的用戶接受程度。

初版:簡單的ab池劃分與細分

在接到第一版需求到時候,需求相當簡單,策劃/運營想要一個可以做abtest的工具,支持細分和多概率組。
基於這個需求,第一版本的abtest需要做三件事情,將玩家的屬性統計出來;將玩家按不同的屬性進行劃分,進而按照不同的概率進行分池;不同業務可以配置在同一個abtest組裏面,比如說玩家看到的公告需要和自己看到的商品協同。
在這一階段:最終實現的abtest方案如下:

  1. 配置表設計
    由於需要將不同的業務可以配置到同一個組裏面,abtest的配置表被設計成了三張表分離:分別是業務表,abtest表和細分表。這是出於一下考慮:
    a. abtest需要有做到不同業務可以協同測試。所以abtest表獨立出來,對開發來說更加直觀。
    b. abtest中有組的概念。而同一組中,對應的細分條件是一致的,也就是說,abtest中,相同的組會共用同一個細分條件,同時,不同的組,也有可能共用同一個細分條件。那麼將細分緯度再抽離出一個表,是符合程序邏輯的。
    c. 在流程設計中,登陸的時候需要根據abtest的細分條件來生成玩家的標籤,因此將細分條件抽出來成表,方便程序實現。
  2. 遊戲測按照策劃的需求,在不同的模塊統計用戶的行爲。在玩家登出的時候進行彙總,形成玩家的屬性。
    由於遊戲中,玩家的不同屬性是分表存儲,不同行爲會到不同的模塊進行處理。如果每次行爲都彙總到某一個特定的表或者模塊中,則會將這個表/模塊變成熱點。舉個例子,在遊戲中,活動模塊會接收玩家的各個事件,比如說登陸,對局結算記錄,購買,獲得,使用物品等事件。那麼該模塊在整個遊戲周邊系統就會就會成爲一個熱點,所有的玩家行爲都有可能對該模塊發送請求。爲了避免abtest也出現這樣的情況(畢竟abtest在遊戲中不應該成爲一個高性能開銷的事情),所以採取的方案就是在不同的模塊分開統計用戶的行爲,降低內網的請求量;在登出的時候做統一處理。
  3. 在玩家登陸的時候,依照配置表和玩家的屬性,生成玩家的標籤,作爲玩家的基礎屬性,附帶在玩家的請求包中。
    在初版的設計中,考慮的最多的就是降低abtest對現有業務的影響,比如說拉取db所造成的影響。如果是在玩家拉取具體業務的時候進行判斷,則需要額外拉取db表,對業務來說會增加時延,同時對業務的改造會比較大。所以考慮的就是將abtest細分條件轉爲玩家的標籤。各個業務只需要判斷一下玩家的標籤即可。
  4. 在玩家獲取商店,活動,公告等配置的時候,根據玩家標籤和概率,來判斷玩家是否命中測試。
    在玩家拉取具體業務的配置時,會取根據玩家的標籤,來判斷玩家是否命中該業務。對業務的改動相當的小。當玩家命中標籤後,會繼續根據玩家的uin尾號來判斷玩家的概率。

這個方案在開發完後,碰到的最大問題是配置表對策劃來說非常難理解。策劃如果需要配置一個abtest活動,需要同時配置三張表。當時策劃的原話是:我配了大半輩子表,第一次見到這麼複雜的表,你牛逼。
這也導致了另一個問題,這個需求的測試非常難測,因爲測試,策劃配表的門檻變得非常的高。 在後續的測試中,發現了很多初版一直遺留下來的bug。

配置拆分:

在初版完成後不久,遊戲的海外版就對配置表有了新的要求-要求abtest能夠支持運營工具配置。這裏介紹一下背景。
我們遊戲有兩種配置方式,一種是走本地對配置表進行配置,另外一種是走運營工具進行配置下發,配置表是落db的。遊戲中對於運營工具配置的支持非常少,在需求提出的時候,只有公告和活動支持運營工具下發,而且實現方式及其複雜。作爲遊戲的開發,我們對於運營工具來下發配置的穩定性深表懷疑。而事實上,在預生產環境,也的確出現過由於該工具導致的奇奇怪怪的問題。
abtest實現中,對於遊戲的打標籤是在登錄這一關鍵路徑中進行的,登錄相關的模塊對穩定性要求很高,如果在該模塊支持運營工具,會帶來很可怕的風險。
此外,在配置表設計中,業務和abtest之間的配置表是有交叉,而且相互影響的。比如說細分表,是各個業務模塊共用的。如果說abtest需要支持運營工具,那麼就存在着,支持運營工具的abtest細分表,需要從運營工具下發;而不支持運營工具的細分表,則需要從配置表中獲得。那麼,一張細分表則會有多個來源,會導致業務邏輯的混亂。
基於上述背景,就需要考慮abtest的配置表修改和拆分了。最終決定修改abtest的配置表和業務流程。
在這一階段,改進的abtest方案如下:

  1. 配置表設計
    原有的abtest表和細分表廢棄。abtest的配置項,放在各個的業務表中。
  2. 玩家標籤和命中測試
    玩家不再有標籤的概念,登錄流程中,不再給玩家打標籤。判斷玩家是否命中放在玩家拉去具體業務時進行。玩家在拉配置時,各個業務需要取拉取玩家的細分緯度,自己進行判斷。

拆分帶來的好處很明顯:
1. 業務之間的配置表不會有交集。策劃配置表不需要跨表了。
2. abtest的配置不會影響到關鍵流程,降低了運營工具對遊戲後臺的風險。
但是拆分也有很多副作用:
1. abtest帶來的性能開銷增大了。拆分到各個業務後,各個業務需要自己取拉取玩家的細分統計,自己取判斷玩家的屬性。
2. abtest更加的侵入具體的業務代碼,干擾業務流程了。
儘管拆分到來的副作用很大,可以說是在遊戲的整個業務邏輯中硬生生插入了一層。但是考慮到這麼做,能夠在最快時間內,避免運營工具衝擊到遊戲的登錄主流程,所帶來的時延和性能開銷相對來說還是可以接受的。畢竟對於業務來說,只要進程還在,邏輯還能正常跑,就能夠正常提供服務。活着纔有dps,掛了就是重大運營事故。

在這一階段,最終實現的abtest方案如下:

  1. 配置表設計
    配置放在各個業務自己的配置表中,原有的兩張單獨的表廢除。
    各個業務的配置表中,增加abtest選項和細分選項。要求策劃配表的時候,同一組的abtest,細分條件需要配置成一樣的。

  2. 遊戲測按照策劃的需求,在不同的模塊統計用戶的行爲。在玩家登出的時候進行彙總,形成玩家的屬性。

  3. 在玩家獲取商店,活動,公告等配置的時候,拉取玩家的統計數據,根據玩家的統計數據和配置的概率,來判斷玩家是否命中測試。
    在玩家拉取具體業務的配置時,同時取拉取玩家的統計數據,通過統計數據實時計算玩家是否命中abtest的細分條件。再依據玩家的uin尾號來判斷玩家的概率區間。

這個方案在很大程度上,導致了abtest 原來對儘量避免對業務造成影響的設計思路 被破壞。 在初版中,abtest在業務層面,在代碼層面上,僅僅是多加了一個if語句的關係。而現在則演變成了侵入業務邏輯,額外增加了很多代碼改動。從這一點來看,初版的這一思路算是完全的失敗了。當然這不是思路本身的問題,只是隨着需求的變更,原有的設計不能再滿足要求了,那麼設計就需要隨着需求變更。
儘管abtest入侵了原有的業務,並帶來了大量的業務改動。但是這一改動在滿足需求的同時,減少abtest配置對主流程的影響,從這一點來看,還算是非常有意義的。事實上,隨着後續需求的進一步提出,以及abtest逐步向精細化運營靠攏,這一改動支撐了部分精細化需求的改動。

從abtest到精細化運營

事實上,不管是abtest,還是精細化運營,遊戲的公共研發體系都是有非常成熟的方案的。但是這只是針對國內的遊戲而言的。儘管目前公司的新遊戲都在想着出海,但是公共研發體系的步伐還是會慢一點。畢竟相對國內公司這麼多遊戲,出海的遊戲還是少的。 但是隨着工作室的遊戲在海外上線,精細化運營也變成了不得不做的事情。這個時候,如果公司的組件無法提供支持,遊戲自己就需要開發精細化運營的功能。而abtest在之前版本的迭代中,具備了部分精細化運營的基礎,將之升級爲精細化運營也是成本最優的選項。
運營在這一版本的需求中,增加了很多細分條件。同時對abtest的功能提了很多新的需求。比如說要求abtest能夠支持更長的時間緯度的統計;玩家命中abtest後需要持續可見,而不會隨着自己條件的變化,導致相應的測試項變得不可見;玩家命中abtest後,需要能夠支持命中失效的時間。比如說命中七天後就不可見等。
在前兩個版本的abtest中,有一個問題是玩家命中條件這件事情是無狀態的。舉一個栗子,如果一個abtest的細分條件是5-10級玩家可見。那麼當玩家10級時,他可以看到測試項,但是當他升級到11級後,那麼他就看不到了。
這個在abtest中對測試會造成影響,但是相對來說是可以容忍的。因爲abtest是短期的事情,但是隨着abtest逐步過渡爲精細化運營。就需要對玩家命中的時間點進行記錄。

由於上一個版本中,abtest已經極大的入侵了各個業務模塊,在這個版本的需求中,對業務模塊對修改就毫無心理負擔了。因此這個版本的改進方案就比較簡單:

  1. 在各個業務模塊自己對db中,存儲這個玩家命中了abtest的記錄,包括命中時間和id等。
  2. 基於玩家命中的記錄,判斷是否需要對玩家展示對應的配置項。

在這一階段,最終實現的abtest方案如下:

  1. 配置表設計
    配置放在各個業務自己的配置表中,原有的兩張單獨的表廢除。
    各個業務的配置表中,增加abtest選項和細分選項。要求策劃配表的時候,同一組的abtest,細分條件需要配置成一樣的。

  2. 遊戲測按照策劃的需求,在不同的模塊統計用戶的行爲。在玩家登出的時候進行彙總,形成玩家的屬性。

  3. 在玩家獲取商店,活動,公告等配置的時候,拉取玩家的統計數據,根據玩家的統計數據和配置的概率,來判斷玩家是否命中測試。
    在玩家拉取具體業務的配置時,同時取拉取玩家的統計數據和命中記錄,通過統計數據和命中記錄判斷玩家能夠看到這個配置項。

這個方案儘管思路上非常簡單,但是完全破壞了abtest不影響業務的設計思路。abtest 現在需要業務拉去玩家的統計數據,而且要求業務記錄下玩家的命中記錄,這就相當於abtest已經完全成爲了業務的一部分了。
而且事實上,在完成這一方案的時候,發現abtest在業務模塊的代碼已經越來越多,從一開始的一個if語句,到第二版一個函數。再到現在,需要有五六個函數,兩個額外的db讀寫,需要嵌入到業務模塊中。儘管從需求的重要程度來說,這麼做是值得的。但是作爲開發而言,新增一個需求,需要寫五六個類似的代碼,並不優雅,而且增加了犯錯的機會。

abtest架構重構

隨着運營的需求不斷變更和abtest需要支持的模塊的增多,原有的abtest架構已經逐漸成爲了一個負擔。每當需求變更,就需要對多個模塊進行同步的更改;每當需要支持新的模塊,就需要侵入新的業務模塊。這不足以支撐起遊戲業務對快速迭代和穩定性的高要求。因此就需要對abtest進行重構。
重構對目的有兩個:

  1. 降低abtest對業務模塊的侵入性。這個侵入性體現在三個方面。一個業務支持abtest所需要的改動儘量降低;abtest的存儲和判斷邏輯聚合到單一的模塊,不再嵌入到別的模塊;abtest的統計不要再嵌入到賬號模塊中。

  2. 將abtest的處理邏輯前置,降低對業務處理性能的影響。
    這個階段的方案如下:

  3. 配置表設計
    配置放在各個業務自己的配置表中,原有的兩張單獨的表廢除。
    各個業務的配置表中,增加abtest選項和細分選項。要求策劃配表的時候,同一組的abtest,細分條件需要配置成一樣的。

  4. 遊戲測按照策劃的需求,在不同的模塊統計用戶的行爲。在玩家登出的時候進行彙總,形成玩家的屬性。

  5. 遊戲中新增abtset模塊。在玩家登錄時,在該模塊先判斷玩家是否命中各個業務的配置,並將結果寫入db。在玩家登出的時候,將玩家數據進行彙總。

  6. 在玩家獲取商店,活動,公告等配置的時候,拉取玩家的命中結果表即可。

這個方案,將原有的abtest中,入侵到業務模塊的代碼給大量抽離出來了。僅保留下拉取數據庫和新增數據的邏輯。
這麼做,可是使abtest對業務的侵入降到最低。這樣可以將abtest對業務的穩定性的影響降到最低,同時將abtest的邏輯聚合到一個模塊,也可以使abtest的迭代更加靈活。
同時,將abtest的統計結果和命中記錄拆分成兩個表格,這樣可以降低對db的壓力。

遇到的問題

  1. 玩家流量分層的問題:
    abtest的玩家分層是一個很常見的問題。在剛開始設計的時候,考慮過這個問題,但是並沒有認真的去做考慮。
    在剛開始的版本,使用一個偏移值來做流量的分層,按玩家uin的尾號作爲命中與否的依據。但是這帶來一個問題,不同的測試,儘管採用了不同的偏移值,但是由於用戶區間是連續的,各個測試之間依然會相互影響。
    因此,在後面的版本中,引入了層級的概念。層級是一個整數,程序會根據這個整數,會將玩家uin不同位數的數字取出來拼成玩家的層級tag。 比如層級1234, 就會將玩家uin第一位數字取出來做千位,將玩家第二位數字取出來做百位,以此類推。
    這樣做的好處有兩個:算法簡單,方便出現問題時定位問題。
  2. 玩家命中記錄和玩家命中記錄持久化的問題:
    abtest是否需要記錄玩家曾經命中與否是一個之前沒有考慮過的問題。abtest在一些短期內測試或者一些所見即所得的場景時,並不會需要考慮這樣的問題。但是在面對一些時間週期較長的場景下,比如說一些持續週期較長的活動,特別是在精細化場景下,玩家命中與否的條件可能隨時會變更,這個時候將玩家命中記錄就顯得很重要了。
    不過在實際運用中,還是有一些小問題。比如說,運營在使用過程中,希望玩家在購買完通行證前,給他推送公告,但是購買完成後就不需要再推送了。這個需求就和上面的需求產生矛盾了。因爲它希望隨着玩家行爲的變更,玩家的命中記錄也要隨之變更。只能說,在開發完一個工具後,用戶就會想出無限種用它的途徑,這個時候出現了功能不符合預期也是正常的。
  3. 效果驗證:
    從程序的角度來講,最需要被驗證的就是abtest是否真的是abtest,玩家的概率是否真的如配置所想要的那樣被隨機。這個時候,程序就需要將命中記錄上報出去,通過宏觀的數據來驗證命中和隨機效果。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章