蘑菇街搜索與推薦架構,從0到1再到100

機器學習 Solr 推薦技術 在線教育 51CTO傳媒 2017-06-06

本文分享蘑菇街在搜索與推薦上踩過的坑,以及在探索路上的經驗總結。從 0 到 1 再到 100,希望大家從中得到一些收穫。

搜索架構的當前現狀

蘑菇街搜索當前架構

蘑菇街當前搜索架構,分為在線和離線兩部分。在線部分主要職責是處理在線的搜索請求。離線部分的主要職責是處理數據流。

蘑菇街搜索與推薦架構,從0到1再到100

在線請求鏈路

整個在線請求鏈路,主要分為五個環節: topn -> qr ->引擎->精排->透出

蘑菇街搜索與推薦架構,從0到1再到100

  • 第一步,請求首先進入 topn 系統,做 ab 配置/業務請求鏈路配置。

  • 第二步,請求進入 QR 改寫系統做切詞,同義詞擴展,類目相關性,插件化等。

  • 第三步,進入 UPS 用戶個性化數據存儲系統。

  • 第四步,投放層得到 UPS 和 QR 兩部分的數據後,放入搜索引擎做召回。搜索主要會經過一輪海選,海選的依據是文本相關性和商品質量,這樣做是為確保召回的商品質量大致可靠。之後會經過多輪初選,過程中會應用到更復雜的算法模型,對海選的結果進行排序。搜索引擎得到粗排的結果約千級別。

  • 第五步,粗排結果進入到精排系統,精排系統主要通過算法,做個性化排序、實時預測,精排和引擎類似,也支持多輪排序。經過精排系統之後,最終把結果透出給業務層。

蘑菇街統一引擎系統

下圖中左側紅色框內是蘑菇街統一引擎系統,包含用戶個性化存儲系統、精排存儲、商品引擎、廣告引擎等。由於這樣的形式維護成本特別高,故做了右圖這個統一的 Zindex 內核架構。

蘑菇街搜索與推薦架構,從0到1再到100

這個架構的最底層是共享內存分配器,再上層是可支持不同數據結構的各種引擎,再上層是索引管理。基於這個架構,不同的引擎可根據各自需求去創建自己的索引。

跟這個架構相關的,就是蘑菇街的運維平臺,是基於 Docker 虛擬化技術做的一個運維平臺,能夠非常快的支持索引創建,包括創建之後整個索引數據的管理。還有就是排序平臺,用來提供算法配置變更服務。

搜索架構離線部分的數據流程

下圖是離線的數據流程的情況,主要職責是數據流的處理,完整的索引數據分為算法數據和業務數據。

蘑菇街搜索與推薦架構,從0到1再到100

算法數據參與排序,整個鏈路從最前端 ACM 打點、再落到整個數據倉庫、經過清洗之後,在數據平臺上跑訓練腳本,得出的特徵導到特徵平臺,再同步到線上。

業務數據的主要來源就是 DB,DB 中主要存儲商品、店鋪之間的數據,業務變更主要基於 mysql bin-log 事件監聽,變更之後做全量和增量。全量每天定時索引操作、增量會流到 MQ,再通過業務拼裝推到線上。

搜索架構的演變歷程

蘑菇街搜索架構主要經歷五大階段:

  • 導購時期(創立~ 2013.11)

  • 電商初期(2013.11 ~ 2014.11)

  • Solr主搜(2015.4 ~ 2016.3)

  • C++主搜(2015.8 ~ 2016.11)

  • 平臺化(2017.1 ~ now)

蘑菇街搜索架構現狀簡化版

為了更清晰直觀進行對比,下圖把當前搜索架構簡化成五大層:業務、投放、排序、召回、數據流

蘑菇街搜索與推薦架構,從0到1再到100

接下來,我們來看看,蘑菇街從最早期,都經歷哪些演變,一步步走到現在。

蘑菇街搜索架構——導購時期架構

下圖是創立~ 2013.11 導購時期的架構,有用到放在 PHP 代碼裡的業務+投放、用 Java 搜索引擎 Solr 做的召回+排序和數據流三層。這個時期,排序需求不是很迫切,更多側重的是商品整體的豐富度和新穎度。簡單理解,熱銷排序等於喜歡乘 10 加上收藏乘 50,基於 Solr 的改造來實現。

蘑菇街搜索與推薦架構,從0到1再到100

在電商轉型初期(2013.11 ~ 2014.11),由於賣自己的商品,流量變得更值錢了,工程師會想法設法去提升流量的效率。同時用戶行為也在增加,產生更多的數據。還有增量管理複雜,數據量大、Optimaize 風險大、導購、廣告和搭配等多類型商品透出等等。其中最明顯挑戰就是排序特徵變多、數據變大、次數頻繁。

蘑菇街搜索架構——轉型初期架構

面對這些挑戰,當時的思路是把算法獨立成單獨 Java 工程做算分,但百萬商品百種排序,算法排序達 G 級別,這些排序數據需要作用於搜索引擎,快速生效,問題是用增量的方式會引來索引碎片的增加,會給線上引擎穩定性帶來波動。故另闢蹊徑,用在 Solr 進程中設置堆外內存來管理這部分排序數據。

蘑菇街搜索與推薦架構,從0到1再到100

總結來說,轉型初期整體的解決方案就是把算法獨立出來單獨去做,把部分分數儘快同步到引擎,進行生效。這樣的方法,當時線上效果很顯著,但隨時間推移又有新問題出來:

  1. 規則排毒-> LTR,算法排序需求多;

  2. 排序靈活性制約:計算好的分數離線推送到 Solr;

  3. Solr 內存壓力:GC /段合併;

  4. 靜態分,相關性差;

  5. 大促相關性問題:搜索“雨傘”,雨傘圖案的連衣裙會排在前面。

Solr 主搜整體架構

針對這些新問題,(2015.4 ~ 2016.3)Solr 主搜改造支持 Rank 插件(Ranker -> Scorer),配置化+動態化,整體架構如下圖。應對相關性問題,新增 QR 系統、應對內存壓力,做 Solr 升級(Docvalues),算法分走動態字段增量,同時投放方式也漸漸形成 Topn 系統,對外對接不同的搜索場景。

蘑菇街搜索與推薦架構,從0到1再到100

Solr 架構解決相關性、算法變更線上排序等問題,但新問題在於雖用機器學習的排序做法,但那個時期主要是爆款模型,有很多個性化需求模型同時對不同人要有不同的排序結果,還有一些重排序或打散等更加複雜的需求。

因 Solr 實現機制的限制,只能做一輪排序,想要改動比較難。另外,Solr 整個索引結構非常複雜,二次開發成本高,內存、性能上也慢慢地暴露出很多問題,同時還有 Java 的 GC 也是不可逾越的鴻溝。

當時多輪排序的需求,除了做一些文本相關性,還相對商品做品牌加權,如想扶持某些品牌、做類目打散等,這些在單輪排序內做不到,原來的方式只能把多輪融合在一個排序中搞定,但效果會很差。

C++ 主搜架構

下圖是 C++ 主搜架構(2015.8 ~ 2016.11)上線,在整個性能和排序方面做了定製,可支持多輪排序、整個內存採用內存方式,由排序體系支撐。

蘑菇街搜索與推薦架構,從0到1再到100

這個階段整體來看,相對是完善的,每層,整個系統都成型,可數據流環節又出現了三個問題:

  1. 全量無調度,都要依靠流程制約;

  2. 增量帶來算法分數不可比,會帶來一些線上排序的抖動;

  3. 業務數據增量對服務接口壓力過大(促銷故障)。

全量的整個鏈路

因為算法序列的整個鏈路靠時間約定,數據容災機制弱,所以大促時,前置任務延遲全量做不了,線上內存幾乎撐爆,經常性全量延時,必須手動去處理。還有算法誤導排序分,導致線上錯亂,增量恢復時間長。

蘑菇街搜索與推薦架構,從0到1再到100

要解決這個問題,蘑菇街首要引入一個基於 Zookeeper 的調度系統,把整個數據流驅動起來同時支持錯誤報警。容災部分的思路就是增加排序 SOS 字段、基於 HBase 定期生成全量快照,快速回檔、單算法字段修復等。

兩次算法增量分數不可比,增量生效特別慢。如時刻 1 算出商品是 90 分,時刻 2 是 60 分,就會引起線上排序抖動,主要因算法兩次序列導致整個數據分佈不同,特別到大促時期,不同時段成交數據變化特別快,商品排序的波動非常明顯,增量數據同一批正常,但兩次見就會出錯。當 0 點大家在瘋狂購物的時候,變更非常頻繁,會導致排序錯亂。算法數據出錯後,生效時間也會比較慢。

蘑菇街搜索與推薦架構,從0到1再到100

上圖的解決方案是通過小全量的方式把算法、分數單獨拖到線上引擎本地,在引擎本地依次一次加載,直接切換的方式,讓每一次算法增量數據的數據加速生效,容災也會加快。

蘑菇街搜索與推薦架構,從0到1再到100

如上圖,由於變更都是 Doc 級更新,每一個字段更新都會調用所有的接口去拼裝成一條完整的數據去更新,這導致業務增量壓力特別大。大促期間,增量 QPS 可以達到幾千~上萬,對下游 40 多個接口的壓力非常大。

蘑菇街搜索與推薦架構,從0到1再到100

如上圖,這個問題解決的思路是讓引擎,包括數據流支持字段更新。只拼裝變更字段、不需要拼裝完整的數據,這需要引擎本身支持才能做到。當時上線,收益非常明顯,關鍵接口 QPS 減少 80% 以上。

平臺化(2017.1 ~ now)是現在正在做的事情。面對 UPS、廣告、商品多套引擎系統與廣告、搜索多套投放系統分別從不同團隊合併過來, 維護成本問題。排序計算需求變得更加複雜,嘗試用非線性模型等方面挑戰,就有了現在整理的架構,思路就是平臺化、統一化,把重複的系統整合、數據流做統一。

搜索架構的經驗總結

這一路走來,整個搜索架構的探索經驗就是在發展前期要簡單快速支持線上業務,之後在逐步演變,來滿足算法的需求,最後在考慮整個利用平臺化、統一化的思路去提升效率,降低成本。

不同階段要有不同的選擇,蘑菇街最早基於 Solr 改寫,待團隊、人員,包括技術儲備上也有實力後,直接重寫搜索引擎,覆蓋算法的離線、在線鏈路,做體系化建設。

他們的後續規劃是新架構整體平臺化繼續深入,在算法方面加強學習,如深度學習框架的研究和使用,在線學習以及圖搜工程體系的建設。

推薦架構的發展概述

蘑菇街的推薦架構已經覆蓋大部分的用戶行為路徑,從使用進入 APP,到下單成交完成都會有推薦場景出現。推薦架構的整個發展分為四大階段:

  • 發展早期(2103.11 ~ 2015.6)

  • 1.0 時期:從 0 到 1(2015.6 ~ 2016.3)

  • 2.0:投放+個性化(2016.3 ~ 2016.12)

  • 3.0:平臺化(2016.2 ~ now)

發展早期(2103.11 ~ 2015.6)推薦的場景並不多,需求也比較簡單,數據離線更新到Redis就好,當時明顯的問題是沒有專門的推薦系統來承載推薦場景、效果跟蹤差、場景對接、數據導入等效率低等。

1.0 時期的推薦架構

從0到1(2015.6 ~ 2016.3)把推薦系統搭建起來,包含 Service 層對接場景、推薦實時預測、自寫的 K-V 的系統用來存儲推薦結果。這裡踩的一個坑是,把實時預測做到離線部分,但其實實時預測更多的是在線流程。

蘑菇街搜索與推薦架構,從0到1再到100

隨著時間推移,場景類型(猜你喜歡、搜相似、店鋪內)、相似場景(首頁、購物車、詳情頁…)不斷增加,算法方面需要實時排序,應對實時的點擊、加購等,還有一些個性化排序需求,如店鋪、類目、離線偏好等。1.0 階段主要面臨三大問題:

  1. 多類型多場景:上線系統不一,缺少統一對接層,成本高;

  2. 場景配置化:場景算法一對一,重複代碼拷貝,維護難;

  3. 個性化+實時:缺系統支持。

2.0 時期的推薦架構

2.0 時期的推薦架構(2016.3 ~ 2016.12)主要解決 1.0 的三大問題,增加投放層 Prism,統一對外對接不同的業務場景,對 Prism 做動態配置和規則模板。個性化實時方面增加 UPS 與精排系統。

蘑菇街搜索與推薦架構,從0到1再到100

2.0 時期推薦架構投放層配置化

2.0 時期推薦架構投放層配置化思路是把不變的部分模板化,可變的部分配置化。系統提供召回組建、數據補全、格式化等模板。當時效果很明顯,321 大促運營位置個性化效果提升 20%+,雙 11 大促,會場樓層個性化提升 100%+。

蘑菇街搜索與推薦架構,從0到1再到100

大促帶來的巨大收益,給整個系統帶來很正面的影響,後續推薦架構又面臨更多的需求與挑戰:

  1. 日益增長的資源位、直播、圖像等場景和類型;

  2. 跟美的融合,跨團隊跨地域的挑戰;

  3. 工程算法用一套代碼,整個策略的開發調試都非常複雜,包括工程部分的職責不清問題;

  4. 由於原來模板化的配置,導致一些簡單場景複雜化。

針對這些問題,蘑菇街需要做的事情就是通用化、平臺化。針對整套系統進行統一推薦方案,自動化整體算法對接核心業務流程、以及和算法人員的職責劃分清晰,提升雙方的工作效率。

3.0 時期推薦架構

3.0 時期推薦架構 (2016.2 ~ now)與搜索架構類似,系統間職能更加明晰,統一和平臺化,主要還是投放層做了改造。

蘑菇街搜索與推薦架構,從0到1再到100

3.0 時期推薦架構投放層細節

3.0 時期推薦架構投放層重要的概念就是場景化,場景應對推薦業務,不同場景會對應不同的策略實現。

蘑菇街搜索與推薦架構,從0到1再到100

推薦架構總結

推薦架構前期,也和搜索架構一樣,需要快速支持推薦業務,不需要花費大量精力去搭建非常複雜的系統。滿足業務、算法等需求後,才是平臺化提升算法、工程雙方的效率。

後續平臺化繼續深入,如針對算法策略的評測和壓測工具方面,全場景智能監控報警 & 容災。算法支持方面,就是 OnlineLearning & 強化學習,根據算法效果來設計新產品。

蘑菇街搜索與推薦架構,從0到1再到100

丁小明,花名小寶

蘑菇街搜索技術團隊負責人

2011年底加入蘑菇街,2013年開始負責搜索團隊,見證了蘑菇街一路蓬勃發展的歷程,也和團隊一起從零起步摸爬滾打,打造了蘑菇街的搜索推薦體系,包括自主研發的C++主搜引擎和廣告引擎、實時個性化推薦系統、基於開源Solr/ES深度定製的實時搜索平臺等。

相關推薦

推薦中...