均一網站 — 資料收集和分析架構 (上)


前言

我們希望能夠使用老師、學生在均一平台產生的資料,幫助功能開發的決策。無奈剛開始做資料分析的時候,沒有完整的資料分析架構去幫助資料分析。經過了一年多的思考和嘗試,現在均一的資料收集和處理系統有一個相較以往完整的雛形,在此篇文章將分享以及回顧這段過程,希望可以幫助到需要自己建立資料處理系統的讀者。

本文分(上)、(下) 兩篇,(上)篇會著重在各種資料的收集,儲存進統一的資料庫,(下)篇則會著重在這些資料後續的處理和應用。

 

均一資料架構圖

 

最初作法:先用既有的 DB 分析看看

均一平台一開始只有網站儲存的 DB 而已,所以先藉著把在 Google Cloud Storage 備份的 DB 資料匯入 BigQuery 的方式,先把網站(Google App Engine)內部的資料備份到 Google Cloud Storage,之後再匯入 BigQuery(線(1))。接著用 BigQuery 內建的語法,來做 Query 和資料分析。當然… 單純用 BigQuery 的 console 來操作資料也太辛苦了,分析結果也很難保存,因此很快就開始用 R studio, Pandas + Ipython 介接 BigQuery 的方式來做資料分析(線(6))。

 

挑戰一:DB 資料不適合/不夠做資料分析

因為一開始存在網站的 DB 目的是為了網站的運作,不是為了使用者行為的分析,因此很多資料分析不到亦或是難以從 DB 重現。
因此我們藉由 Google App Engine 內建的 Streaming Logging 的方式,把資料 Logging 到 BigQuery (Logging Data),這樣做相比於匯入 Google App Engine 內建 DB 到 BigQuery (路線 1)有以下優點,因此,至今我們大部分的資料分析都是使用路線(2) 的方式匯入的資料,只有少數資料表仍然仰賴網站 DB 的匯入。
 
Logging Data 的好處:

         1. 更具有彈性(不需要建立對應的 DB)

         2. 更即時(DB 的匯入是 Jenkins 工作排程,非即時)

         3. 在運算、儲存資源的運用上也更有效率 (DB 一次一定是整個匯入,如果是跟時間 Logging 有關的 DB,其實每週匯入重複的資料量很大。)

 

挑戰二:不容易收集到 Client 端行為

隨著分析的需求和作法越來越多樣,我們希望能更直接看到均一網站 Client 端的使用者行為(ex. 使用者按了哪些按鈕、從哪一頁逛到哪一頁云云),所以還想把使用者在前端的行為也 Logging 到 BigQuery,這單純用路線(2) 是做不到的。
 
我們最後決定研究看看有沒有機會直接把 Google Analytics (GA) 裡面的資料自動匯出來,會這樣想的原因是因為

        1. 可以儘量減少在系統中的實作

        2. 均一網站內部已經埋了很多 GA page view 和 GA event,這樣就不用重新埋了

        3. GA 另外還有幫忙記錄了很多資料,包含使用者的裝置型號、使用者位置等資料,希望也可以整合進自己的 BigQuery 使用

解法:
基於上面三個原因,我們研究了 GA 的各種 API,結果真的有一種方式,可以達成我們的需求:把網站 Logging 到 Google Analytics 的所有資料匯出來(目前是在 Jenkins 上每天跑一次),再存到 BigQuery (或是其他的資料庫)。其實 GA API 本身沒有想要支援這樣的功能(倒出原始資料),它的 API 只想要給你資料統計之後的結果,但是因為它同時有 Custom Dimension,所以只要確認你設定的 Custom Dimension 可以造成每比資料都是獨一無二的,那麼統計的結果也就會跟這一比資料的內容一致了(GA 每天提供足夠多的 Request 次數讓我們把所有的原始資料匯出)。我們有在 GitHub Open Source 詳細的作法,叫做 dauGA (倒 GA) ,希望可以給大家一點幫助。

 

挑戰三:加入 AB test ,進行 Randomize Control 的實驗

截至目前為止的作法,並不包含 AB test 的功能,我們當初承襲可汗學院,使用 Open Source 套件 gae_bingo 來做 AB test ,無奈 gae_bingo 自成一套體系,無法跟我們其他儲存的資料做對照,另外 gae_bingo 很吃記憶體、以及因為實作上牽涉到 Google App Engine 的底層,容易產生一些難解的 Bug 。經過討論以後,我們決定把 gae_bingo 從均一當中拔掉,並參考它的設計,實作了一個很簡單的 AB test 工具,並且和現有的 Logging 機制(路線(2)) 做整合。
 
實作方法:
我們利用使用者的 unique id ,加上一些 random 參數,一起 hash 成數字後,取 mod 的方式來做使用者分群,(ex. 如果 A 組:B 組 = 9 : 1 的話,就把所有使用者 hash 過後的結果取 mod 10,餘數是 0 的取 B 組,其他 A 組)。我們把分組的結果也透過路線(2)的方式也存在 BigQuery,基本上只存三個欄位:unique id, 什麼實驗, 以及哪一組。要參照實驗的結果,就把不同的實驗組別,藉由使用者的 unique id 和其他 BigQuery 的資料表做 JOIN,然後再做各種統計上的分析。
 
這樣的作法的好處,除了解決之前 gae_bingo 帶來的問題以外:

        1. 讓系統的負擔減小很多

        2. 因為能夠使用到 BigQuery 裡面我們各種不同 source 的資料,AB test 能夠看的結果瞬間多了很多。

 

 

心得小結

回顧以上介紹的三種收集資料的管道,我個人認為第二項,把資料從 Server Logging 到外部資料庫是初期很關鍵的工作。難度不高,但是已經能做很多不同的分析了。再這邊分享一個「設計 Logging 的 Table 」的心得,我們的作法是先確定邊界條件:確認 Logging 後的資料可以恢復任何一個時間點網站情況的 Snap Shot,第二個考量的是每個欄位的可讀性,第三點是資料欄位越少越好。

舉例來說,我們有教練身分、學生身分和班級群組:一個教練和學生是多對多的關係,教練又可以把多個學生歸類為一個班級方便管理。當初設計教練、學生建立關係的 Logging 的時候,就要確保只要我們有 2016 年 1 月 1 號全網站教練、班級、學生三者之間的關係,從此之後我們可以藉由 Logging 而得的資料,去重現 2016 年之後任意時間點的教練、班級、學生關係。用這樣的作法來確保收集的資料欄位的完整性。

這樣林林總總,總算把網站前前後後上上下下的資料都統整到資料庫(BigQuery) 了,但是離「讓大家都可以得心應手地處理數據」這個目標還有一大節差距。

首先,資料的來源不一、系統的 Bug、再加上一些外部匯入的資料,造成資料內容上有許多的矛盾和不一致。此外,在軟體組做資料分析的成員增加後,更有許多溝通和上手各個不同資料表的困難,因此資料後續的處理和各種使用的管道也是格外重要,這部份會在(下)篇中提到。

 

Leave a comment

你的電子郵件位址並不會被公開。 必要欄位標記為 *