KOL Radar 網紅資料庫十倍率成長的挑戰
Johnny 在 iKala KOL Radar 擔任 senior software engineer 負責架構設計部分,在過往也待過 HandsUP,FBBuy 等產品,擁有參與過不管是 0 → 1 或是 1 → N 等豐富經歷,本篇將會分享在 KOL Radar 資料庫十倍率成長所面臨的挑戰。
這篇將分享 KOL Radar 在拓展亞太地區網紅服務而做的系統升級。技術聯手產品團隊從原本 20 萬網紅、 1 億筆貼文,成長 5 倍到 100 萬網紅、5 億筆以上貼文,使用 Elasticsearch 冷熱架構規劃來解決。
以下是我們遇到的問題與挑戰。
問題陳述
- 目前所有資料都會儲存進去 MySQL,因此有些表資料已經破億,若未來持續增長了話會影響查詢以及寫入效能,且往後新增欄位時候 migration 都是挑戰。
- 資料四散在不同 storage(e.g. MySQL & Elasticsearch & MongoDB) ,導致應用端要使用時候需要個別去撈取資料 (其中針對 Elasticsearch 又使用 for loop query,浪費不少 I/O 資源)。
預期目標
- 能有效區分冷、熱資料,且能依照 KOL Radar 系統特性只儲存一年份可以做搜尋,但刪除資料需要有能力可以備份回來,以便未來需要使用或是分析。
- 除了能擴張至少 100 萬筆,還要可以再往上擴充 1,000 萬筆的擴充性,就算未來資料面增長,應用端也無需做大調整。
- 搜尋網紅是我們產品核心功能,需要有完善的備份措施以及回復手段。
解決方案
有足夠大的彈性來支撐資料面的增長,軟體方面也要保留未來可以隨時抽換實作方式的可能性。
資料儲存我們選擇了 Elasticsearch,主要有以下幾個優點
- life cycle的功能,讓我們有效管理冷熱資料,還有完整自動備份功能。
- 天生就是分散式資料庫,除了高可用(HA)以外還可以水平擴展儲存空間。
- 現階段 KOL Radar 產品本來就有使用,只需要再針對細節作協調整即可,時程上來說也不會太趕,整體架構也保持 KISS 原則(Keep It Simple, Stupid),越簡單越單純越好。
在中間可以看到多規劃了一層「抽象層」,降低應用層去抓取資料的複雜度,也保留彈性讓未來更換實作方式。
技術實現
資料儲存
依照資料特性可以區分兩大項:搜尋網紅資料、網紅成效報告。
搜尋網紅資料
- 資料量體比較大
- 僅需儲存一年內的資料 (超過一年資料要有手段可以隨時拿回來幫做分析,或是未來其他功能需要)
- 有效區分冷熱資料
網紅成效報告
- 資料量體較小
- 報表相關資料需永久儲存
透過 Elasticsearch Hot-Warm Architectures,讓我們有效管理冷熱資料,且又可以設定 life cycle 超過一年後自動備份刪除,真的是有夠讚!
也因為有備份,未來如果產品應用需要把一年前資料拿出來分析,
也是按個按鈕的事情,因此保留了很大的彈性。
INDEX 設計與管理
搜尋網紅資料
- 熱資料寫入全部匯流進去 Hot 機器
- 依據 [時間] or [index] 大小 會搬移到 Warm
- 在過渡到 Warm 階段時,會 shrink + force merge + readonly 以保持最佳 search 狀態
- Replicas * 1
網紅成效報表
- 熱資料寫入全部匯流進去 Hot 機器
- 因為資料量體少且保持查看網紅報表有良好的體驗,因此目前沒設定 lifecycle 就先放在 Hot,隨時觀察
機器方面我們為了少開點機器,先把 Warm、Cold 共用
- Hot * 3 (4 vCPUs ,32 GiB, disk: 300GB)
- Warm & Cold * 4 (2 vCPUs,16 GiB, disk: 600 GB)
抽象層
我們特地規劃了一層「抽象層」,隔開原本直接相連的不同應用與伺服器層,讓產品可以依照下列方法搜尋:
網紅資料(influencers)
- 搜尋 AI 標籤、AI 受眾數據
- 搜尋關鍵字 (name、post….)
- 各個分析指標 (粉絲數、互動率 ….)
網紅貼文資料(posts)
- 誰 發了哪些貼文
- 時間內 有哪些貼文
- 搜尋關鍵字 (title、content、bio)
網紅貼文留言資料(comments)
- 哪則貼文底下的留言
實作方法,我選擇以開發 SDK 方式作處理。
原先有考慮是否開一個 API server 但考量的在初期開發上會稍微麻煩一點,畢竟開完 API server 還要自己去串起來,沒辦法像 SDK 一樣寫完,應用層就有現成的 struct 可以用而且還可以省一段 I/O,減少錯誤發生率以及延遲,未來如果真的有需要改成打 API Server 也只要稍微修改下 SDK 實作即可。
隱藏了「應用層」需要深入理解資料的讀取的複雜度,保留了未來若是資料量體增長而需要調整實作,但仍不會影響到「應用層」的 code。
另外 SDK 部分,回傳資料集都會是整理過的資料並且補上一些有用的 helper function,「應用端」就算有其他需求,也可以自行擴充組裝。
// SDK response example
// 提供最底層資料,使用者在基於以下 interface 擴充想要顯示的資料
type DatahubStatisticContact interface {
GetGeneralPurposePosts() []*GeneralPurposePost
GetGeneralPurposePostByID(postID string) (*GeneralPurposePost, bool)
....
}
// 應用端 可以自行補充擴充實作
type ExpansionStatistic struct {
DatahubStatisticContact
}
結語
在寫這篇文章的時候 2023.Q1 已經剩下 1/3 了 (上述實作於 2022.Q4),到目前實際跑起來都有如預期的表現以及擴充,但還是有遇到幾個有趣的小問題,有機會再來分享!
除了成長到 100 萬筆網紅除了上述調整外,我們還規劃了相對應的資料來源搭配內部資料介接的 ETL pipeline,都會在後續的文章一起慢慢分享 XD!
最後我們現在還有在徵才喔,如果你也是擁抱改變且對技術充滿熱情的夥伴,歡迎投遞履歷、來聊聊~
感謝花時間讀這篇文章,如果覺得有得到收穫,不要吝嗇給個 「掌聲鼓勵」,有什麼想討論的也可以留言讓我知道!