丁小明,花名小寶,蘑菇街搜索技術團隊負責人。2011年末加入蘑菇街,2013年開始負責搜索團隊,見證了蘑菇街一路蓬勃發展的歷程,也和團隊一塊兒從零起步摸爬滾打,打造了蘑菇街的搜索推薦體系,包括自主研發的C++主搜引擎和廣告引擎、實時個性化推薦系統、基於開源Solr/ES深度定製的實時搜索平臺等。前端
小寶·蘑菇街搜索技術團隊負責人mysql
如下內容根據小寶老師在WOTA2017 「電商大促背後的技術挑戰」專場的演講內容整理。算法
我將和你們分享蘑菇街在搜索推薦上踩過的坑及在探索路上的經驗總結。咱們的經驗雖算不上業界最佳實踐,但也是一步步從0到1再到100,但願你們能夠從中獲得一些收穫。sql
蘑菇街搜索當前架構數據結構
如上圖,是蘑菇街當前搜索架構,分爲在線和離線兩部分。在線部分主要職責是處理在線的搜索請求。離線部分的主要職責是處理數據流。架構
在線請求鏈路框架
如上圖,是整個在線請求鏈路,主要分爲topn->qr->引擎->精排->透出五個環節。運維
第一步,請求首先進入topn系統,作ab配置/業務請求鏈路配置。機器學習
第二步,請求進入QR改寫系統作切詞,同義詞擴展,類目相關性,插件化等。ide
第三步,進入UPS用戶個性化數據存儲系統。
第四步,投放層獲得UPS和QR兩部分的數據後,放入搜索引擎作召回。搜索主要會通過一輪海選,海選的依據是文本相關性和商品質量,這樣作是爲確保召回的商品質量大體可靠。以後會通過多輪初選,過程當中會應用到更復雜的算法模型,對海選的結果進行排序。搜索引擎獲得粗排的結果約千級別。
第五步,粗排結果進入到精排系統,精排系統主要經過算法,作個性化排序、實時預測,精排和引擎相似,也支持多輪排序。通過精排系統以後,最終把結果透出給業務層。
蘑菇街統一引擎系統
如上圖,左側紅色框內是蘑菇街統一引擎系統,包含用戶個性化存儲系統、精排存儲、商品引擎、廣告引擎等。因爲這樣的形式維護成本特別高,故作了右圖這個統一的Zindex內核架構。這個架構的最底層是共享內存分配器,再上層是可支持不一樣數據結構的各類引擎,再上層是索引管理。基於這個架構,不一樣的引擎可根據各自需求去建立本身的索引。
跟這個架構相關的,就是咱們的運維平臺,是基於公司Docker虛擬化技術作的一個運維平臺,可以很是快的支持索引建立,包括建立以後整個索引數據的管理。還有就是排序平臺,用來提供算法配置變動服務。
搜索架構離線部分的數據流程
如上圖,是離線的數據流程的狀況,主要職責是數據流的處理,完整的索引數據分爲算法數據和業務數據。
算法數據參與排序,整個鏈路從最前端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)五大階段。
蘑菇街搜索架構現狀簡化版
爲了更清晰直觀進行對比,我把當前搜索架構簡化成如上圖所示的業務、投放、排序、召回、數據流五大層。接下來咱們來看看,咱們從最先期,都經歷哪些演變,一步步走到如今。
蘑菇街搜索架構導購時期架構
如上圖,是~2013.11導購時期的架構,有用到放在PHP代碼裏的業務+投放、用Java搜索引擎Solr作的召回+排序和數據流三層。這個時期,排序需求不是很迫切,更多側重的是商品總體的豐富度和新穎度。簡單理解,熱銷排序等於喜歡乘10加上收藏乘50,基於Solr的改造來實現。
在電商轉型初期(2013.11~2014.11),因爲賣本身的商品,流量變得更值錢了,工程師會想法設法去提高流量的效率。同時用戶行爲也在增長,產生更多的數據。還有增量管理複雜,數據量大、Optimaize風險大、導購、廣告和搭配等多類型商品透出等等。其中最明顯挑戰就是排序特徵變多、數據變大、次數頻繁。
蘑菇街搜索架構轉型初期架構
面對這些挑戰,當時的思路是把算法獨立成單獨Java工程作算分,但百萬商品百種排序,算法排序達G級別,這些排序數據須要做用於搜索引擎,快速生效,問題是用增量的方式會引來索引碎片的增長,會給線上引擎穩定性帶來波動。故另闢蹊徑,用在Solr進程中設置堆外內存來管理這部分排序數據。
總結來講,轉型初期總體的解決方案就是把算法獨立出來單獨去作,把部分分數儘快同步到引擎,進行生效。這樣的方法,當時線上效果很顯著,但隨時間推移又有新問題出來:
規則排毒->LTR,算法排序需求多;
排序靈活性制約:計算好的分數離線推送到Solr;
Solr內存壓力:GC/段合併;
靜態分,相關性差;
大促相關性問題:搜索「雨傘」,雨傘圖案的連衣裙會排在前面;
Solr主搜總體架構
針對這些新問題,(2015.4)Solr主搜改造,支持Rank插件(Ranker->Scorer),配置化+動態化,總體架構如上圖。應對相關性問題,新增QR系統、應對內存壓力,作Solr升級(Docvalues),算法分走動態字段增量,同時投放方式也漸漸造成Topn系統,對外對接不一樣的搜索場景。
Solr架構解決相關性、算法變動線上排序等問題,但新問題在於雖用機器學習的排序作法,但那個時期主要是爆款模型,有不少個性化需求模型同時對不一樣人要有不一樣的排序結果,還有一些重排序或打散等更加複雜的需求。因Solr實現機制的限制,只能作一輪排序,想要改動比較難。另外,Solr整個索引結構很是複雜,二次開發成本高,內存、性能上也慢慢地暴露出不少問題,同時還有Java的GC也是不可逾越的鴻溝。
當時多輪排序的需求,除了作一些文本相關性,還相對商品作品牌加權,如想扶持某些品牌、作類目打散等,這些在單輪排序內作不到,原來的方式只能把多輪融合在一個排序中搞定,但效果會不好。
C++主搜架構
如上圖,是C++主搜架構(2015.8~2016.11)上線,在整個性能和排序方面作了定製,可支持多輪排序、整個內存採用內存方式,由排序體系支撐。這個階段總體來看,相對是完善的,每層,整個系統都成型,可數據流環節又出現了三個問題:
全量無調度,都要依靠流程制約
增量帶來算法分數不可比,會帶來一些線上排序的抖動
業務數據增量對服務接口壓力過大(促銷故障)
全量的整個鏈路
如上圖,是全量的整個鏈路,算法序列的整個鏈路靠時間約定,數據容災機制弱。因此大促時,前置任務延遲全量作不了,線上內存幾乎撐爆,常常性全量延時,必須手動去處理。還有算法誤導排序分,致使線上錯亂,增量恢復時間長。
要解決這個問題,咱們首要引入一個基於Zookeeper的調度系統,把整個數據流驅動起來同時支持錯誤報警。容災部分的思路就是增長排序SOS字段、基於HBase按期生成全量快照,快速回檔、單算法字段修復等。
兩次算法增量分數不可比,增量生效特別慢。如時刻1算出商品是90分,時刻2是60分,就會引發線上排序抖動,主要因算法兩次序列致使整個數據分佈不一樣,特別到大促時期,不一樣時段成交數據變化特別快,商品排序的波動很是明顯,增量數據同一批正常,但兩次見就會出錯。當0點你們在瘋狂購物的時候,變動很是頻繁,會致使排序錯亂。算法數據出錯後,生效時間也會比較慢。
如上圖,咱們的解決方案是經過小全量的方式把算法、分數單獨拖到線上引擎本地,在引擎本地依次一次加載,直接切換的方式,讓每一次算法增量數據的數據加速生效,容災也會加快。
如上圖,因爲變動都是Doc級更新,每個字段更新都會調用全部的接口去拼裝成一條完整的數據去更新,這致使業務增量壓力特別大。大促期間,增量QPS能夠達到幾千~上萬,對下游40多個接口的壓力很是大。
如上圖,這個問題解決的思路是讓引擎,包括數據流支持字段更新。只拼裝變動字段、不須要拼裝完整的數據,這須要引擎自己支持才能作到。當時上線,收益很是明顯,關鍵接口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時期的推薦架構
1.0時期:從0到1(2015.6~2016.3)把推薦系統搭建起來,包含Service層對接場景、推薦實時預測、自寫的K-V的系統用來存儲推薦結果。這裏踩的一個坑是,把實時預測作到離線部分,但其實實時預測更多的是在線流程。
隨着時間推移,場景類型(猜你喜歡、搜類似、店鋪內)、類似場景(首頁、購物車、詳情頁…)不斷增長,算法方面須要實時排序,應對實時的點擊、加購等,還有一些個性化排序需求,如店鋪、類目、離線偏好等。1.0階段主要面臨三大問題:
多類型多場景:上線系統不一,缺乏統一對接層,成本高;
場景配置化:場景算法一對一,重複代碼拷貝,維護難;
個性化+實時:缺系統支持;
2.0時期的推薦架構
如上圖,2.0時期的推薦架構(2016.3~2016.12)主要解決1.0的三大問題,增長投放層Prism,統一對外對接不一樣的業務場景,對Prism作動態配置和規則模板。個性化實時方面增長UPS與精排系統。
2.0時期推薦架構投放層配置化
如上圖,2.0時期推薦架構投放層配置化思路是把不變的部分模板化,可變的部分配置化。系統提供召回組建、數據補全、格式化等模板。當時效果很明顯,321大促運營位置個性化效果提高20%+,雙11大促,會場樓層個性化提高100%+。
大促帶來的巨大收益,給整個系統帶來很正面的影響,後續推薦架構又面臨更多的需求與挑戰:
日益增加的資源位、直播、圖像等場景和類型;
跟美的融合,跨團隊跨地域的挑戰;
工程算法用一套代碼,整個策略的開發調試都很是複雜,包括工程部分的職責不清問題;
因爲原來模板化的配置,致使一些簡單場景複雜化。
針對這些問題,咱們須要作的事情就是通用化、平臺化。針對整套系統進行統一推薦方案,自動化總體算法對接核心業務流程、以及和算法人員的職責劃分清晰,提高雙方的工做效率。
3.0時期推薦架構
3.0時期推薦架構 (2016.2~now)與搜索架構相似,系統間職能更加明晰,統一和平臺化,主要仍是投放層作了改造。
3.0時期推薦架構投放層細節
如上圖, 3.0時期推薦架構投放層重要的概念就是場景化,場景應對推薦業務,不一樣場景會對應不一樣的策略實現。
推薦架構前期,也和搜索架構同樣,須要快速支持推薦業務,不須要花費大量精力去搭建很是複雜的系統。知足業務、算法等需求後,纔是平臺化提高算法、工程雙方的效率。後續平臺化繼續深刻,如針對算法策略的評測和壓測工具方面,全場景智能監控報警&容災。算法支持方面,就是OnlineLearning&強化學習,根據算法效果來設計新產品。
以上內容根據丁小明 老師在「電商大促背後的技術挑戰」的演講內容整理。若有投稿、尋求報道意向技術人請聯絡 wangxy@51cto.com