介紹 vivo 應用商店推薦系統如何高效支撐個性化的推薦需求。算法
商店的應用數據主要來源於運營排期、CPD、遊戲、算法等渠道,成立推薦項目以後也沒有變化,發生變化的是由推薦系統負責和數據源進行對接,商店服務端只須要和應用推薦系統進行對接便可。設計模式
若是讀者覺得咱們單純是把商店服務端代碼給照搬到推薦系統這邊來了那就真的是too young too simple 了,不作優化或者升級直接copy一個系統是不可能的,這輩子都不可能。如下我將介紹咱們如何去設計和規劃應用推薦系統的。架構
在筆者眼中,商店應用推薦系統除了要具有高性能、高可用性及核心指標的監控能力以外,還有一個核心的能力就是高效支撐商店流量場景接入個性化推薦。框架
如何定義高效支撐?ide
分享咱們一個應用推薦的策劃case看看:性能
在xx場景下,大數據
若是主應用A屬於應用類,優化
- 則首先從從x1數據源去取Q1隊列。
- 而後從x2數據源去取Q2隊列。
- 而後用Q2隊列去截斷Q1隊列,交集以後進行同開發者過濾和一級分類過濾。
- 若是交集爲空則用Q2去兜底,而後取交集隊列的n1和n2 位置上的元素做爲返回隊列。
- 若是前面都沒有取到數據的話從大數據xxx表中按照主應用下應用點擊的機率取點擊率最高的分類下的n個,同時須要對這些數據進行隊列內的同開發者過濾。
若是主應用A屬於遊戲類,插件
- 則xxxx
- 進行二級分類過濾
- 若是量不足的話,則從x(n)取數據而後進行處理,
- 若是數據不足3個的話,須要從周榜單中取同一級分類下的應用按照下載排行進行兜底。
沒錯,讀者朋友不要懷疑本身,爲了避免把各位讀者大大繞暈,咱們這裏只是挑選了一個簡單的需求。實現這麼一個功能也沒有什麼大不了的,可是當這種個性化推薦需求有幾十個,後面還可能一致擴展下去的時候會不會內心發慌?來,簡單看下咱們如今個性化推薦的一部分需求,如圖(一)所示:線程
圖(一)
使用商店服務端以前的case by case的開發方案,不管如何都沒法實現上文中描述的要支撐商店高效接入推薦場景了,接着就是咱們如何去實現優化的過程了。
爲了更好的說明解決思路,咱們從實際思考過程出發,一步步講解問題的解決過程。
單純從策劃上面來講,咱們每一個場景都須要至少作如圖(二)中的幾件事情:
圖(二)
筆者從開發便捷性出發,對模型進行了進一步的調整,調整後爲圖(三)
圖(三)
獲取隊列後對隊列進行安裝過濾和隊列內過濾(如主應用同開發者過濾等)能夠進行流程合併,主要有以下的緣由
到圖(三)這裏,讀者會發現咱們依然沒有可以解決咱們前面提到的各類推薦場景裏面的差別化過程。
其實在接觸幾個需求之後,咱們會發現,想要在一套代碼裏面去解決這麼大的差別性,幾乎不可能,或者即便實現了,那麼也會讓代碼變得無比複雜。與其這樣子,咱們還不如正視這種差別性,讓差別在場景插件裏面去實現,咱們花更多的精力去打理主幹。
那麼爲了支持讓場景可以具有靈活的擴展能力,筆者在基於圖(三)的基礎上增長了四個環節:
拓展後的流程圖如圖(四)所示
圖(四)
通過上述的分析可知,咱們能夠儘量的把個性化的場景內容放在插件層實現,框架層負責加載按場景加載場景插件的具體個性化推薦邏輯。
系統從分層思路上講從上至下共分爲:插件層,框架層,協議適配層,數據源服務層,原子服務層,基礎服務層,上層經過 SDK 依賴下層的服務(接口),各層次職責爲:
至此,相信你們都知曉了,針對於個性化的推薦,咱們的開發工做最終將聚焦於開發場景插件,不須要再額外開發每個業務流程了。
應用推薦系統架構
在完成第三步總體邏輯框圖設計以後,咱們從場景參數定義,服務設計原則,設計模式使用,場景熱插拔等方面進行了相關的方案研究並最終實現了方案的落地。
爲實現推薦場景足夠通用,咱們將數據源層,原子服務層,基礎服務層的內容進行了服務配置的映射,經過在配置中定義對應的配置項來實現服務的映射和組合,針對於差別性的內容在插件層進行實現。以以下的配置項示意圖來講明:
實現服務原子化與服務惟一化對本系統相當重要,在實現過程當中是嚴格遵守以下兩點來:
應用推薦依賴的三方RPC服務及內部的一些過濾邏輯都封裝成了細粒度的原子服務(方法)的SDK。SDK中的內容不包含個性化推薦場景的具體業務性的能力,體現的重點是基礎功能項,業務內容須要在場景插件中進行實現,統一類型的服務儘量支持組合。
服務惟一化在對於實現系統的收斂和代碼規模可控相當重要,咱們也是不斷的在朝着這個努力。各服務層都是以SDK的形式對外提供相關的功能,在SDK中實現服務調用入口的惟一性。
系統中使用了較多的設計模式來優化總體架構,以下重點來介紹使用的模板設計模式、策略模式及組合模式:
在獲取推薦原始隊列中使用了模板設計模式和策略模式來實現此過程。
使用模板設計模式的好處顯而易見,可以容易促進此部分處理邏輯流程化。
針對不一樣的數據源,須要使用不一樣的數據源服務和方法,使用策略模式的好處是便於定義在不一樣場景下對不一樣的接口的調用。
同類型的原子服務或者方法儘量支持組合模式,這種會爲後續的擴展提供很大的便利性。
以實際的實現方法來講明,在咱們定義過濾類型的時候,支持傳入多個過濾類型,上層業務在使用的時候按需傳入便可。使用組合的設計模式在提高擴展性方面起到了巨大的做用。
系統中爲實現場景之間的隔離和互不干擾,筆者使用了Java SPI的方式,在框架層定義了場景接口,接口實現類則在各個場景在獨自的Jar中實現。這種方式有助於插件程序對框架層和基礎服務層的侵入性降到最低。
之前商店服務端在各個接口的service層寫完整的推薦隊列獲取、融合、組裝、過濾邏輯,有大量的重複內容,且隨着版本的不斷迭代,有不少版本不一樣的處理邏輯夾雜在一塊兒,致使改造難升級難,牽一髮動全身。目前應用推薦系統在兩個方向帶來較大改善:
經過上述相關的方案落地,針對於各個推薦場景,咱們大概減小了75%的開發工做量,同時bug率也獲得大幅度的下降。
做者:vivo-Huang Xiaoqun