一.前言
二.搜索系統架構演進
2.1.到家搜索系統1.0
基于LBS搜索召回場景
建立“可用”的搜索系統
小結
2.2.到家搜索系統2.0
重構召回
排序模型小試牛刀
建立索引容災能力
小結
2.3.到家搜索系統3.0
精細化多路召回
模型升級 算法賦能
路由平臺自動容災
三.搜索系統整體架構
四.展望與總結
京東到家作為行業領先的即時零售電商平臺,依托達達快送的高效配送和大量優秀零售合作伙伴,為消費者提供海量商品小時達的極致服務體驗。隨著平臺中的商品供給日益豐富,幫助用戶準確尋找目標商品的能力就會顯得越來越重要,而搜索系統在電商平臺中即承擔著這樣的職責。
在到家平臺中,搜索系統承接了多個主要流量入口,在不同業務場景下為用戶提供了多元化的關鍵字商品檢索能力。目前,搜索系統在平臺中覆蓋的主要場景有首頁搜索、頻道頁搜索、秒殺活動頁搜索、券購搜索及到家小程序平臺搜索等,如下圖所示:
隨著到家業務發展,到家的用戶量級也在持續增加,為了滿足用戶購物需求,給用戶一個便捷的購物體驗,搜索系統一直在持續地進行架構迭代和策略升級。本文將對到家搜索系統架構演進歷程進行詳細介紹。
由于到家是基于LBS的即時零售業務場景,所以在搜索系統架構上與傳統電商搜索相比也會有所區別。基于LBS的搜索系統在保證商品相關性和排序結果合理性的同時還要通過地理位置因素對召回商品范圍進行限定。在到家系統中,我們采取的方法是通過墨卡托投影原理將門店的配送范圍映射為多個有限區域塊,再結合倒排索引找出覆蓋目標位置的門店供給列表。對應到搜索場景中,我們所需要做的就是在給定的門店列表范圍內通過Query進行高效地商品查詢。
在到家發展初期,搜索系統設計思路以簡單、可用為目標,架構上采用分層單體架構。在實現上,通過對當前供給門店列表進行ES terms查詢來保證LBS條件限定,而Query與商品的匹配主要依靠對Sku名稱進行ES的query_string查詢。同時,對用戶輸入的Query會通過分詞方式進行簡單的品牌品類成分信息提取,并用于對查詢語句的boost提權中。ES查詢結果順序就是搜索系統的返回順序,分頁也交由ES來控制。這樣一來,就實現了1.0版本的到家搜索系統。
隨著業務的發展,平臺上門店和商品的供給數量呈爆發式增長,最初這版搜索架構在業務支持上顯得愈發吃力。主要體現在以下幾點:
1. ES深分頁瓶頸在召回期間通過ES的from size方式進行分頁控制。在深度分頁情況下,這種查詢方式非常低效,查詢性能會直線下降。
2. 缺乏完整召回能力由于通過ES進行分頁控制,所以每次請求搜索服務內部只能從ES拿到當前頁的返回數據,無法得到完整召回數據。但一個完整的搜索系統應該包含對搜索結果多維度篩選功能、搜索結果聚合展示功能,如果每次只能拿到一頁數據,那么在業務玩法上就會受到極大的限制。
3. 排序干預能力有限在商品搜索場景中,ES的bm25評分可以反映出Query與Sku名稱間的文本相關性,但除此之外,搜索排序邏輯還需要關注商品的價格、評價、門店信用、商家質量、促銷力度等維度特征,僅通過bm25評分作為排序依據是遠遠不夠的。但如果所有排序因素都通過ES加權語句實現,最終查詢語句就會變得十分復雜,并且在索引中還要維護所有排序特征信息,這顯然不太現實。所以,需要建立一套獨立的搜索排序服務來承接這樣的職責。
4. ES集群單點依賴搜索業務最基本的能力就是召回,而召回能力又建立在了底層索引數據基礎之上。在搜索1.0版本中底層索引由一套ES集群支撐,但這就會造成整個搜索系統對這套ES集群的單點依賴,如果ES出現問題那么整個搜索業務就會面臨癱瘓的風險。
將1.0版本搜索系統中的主要問題進行歸類可以發現,除了底層集群單點依賴之外,其余三個問題之間都有著直接或間接關系。
ES分頁依賴 ——> 無法完整召回 ——> 排序干預能力有限
所以,優化工作的核心目標是要替換掉當前的ES分頁方式,將全部命中數據完整召回。基于以上思考,我們提出了以下方案:
棄用ES分頁,全量召回內存分頁
抽象排序模塊,獨立服務化部署
首先需要考慮的問題是如何將全量數據召回到內存中。如果from 0 size n設置一個較大的數值,那么ES每一個分片均會召回n條數據后再匯總重排,引發上文中提到的深分頁問題。而ES的另外兩種分頁方式scroll和search after更是不滿足C端場景使用需求,尤其是scroll在高并發場景下還會有極大的性能風險。相比之下,還是from size的查詢方式更適合當前C端搜索場景需要。
在確定from size查詢方式后,我們嘗試找到一個即滿足業務需求又符合性能要求的size臨界值。隨著size增大,ES的查詢性能持續下降。例如,在600qps和5000qps場景分別測試不同size查詢性能,得出如下結果:
并發 | size=1000 |
size=1500 |
size=2000 |
---|---|---|---|
600qps | TP99=80ms | TP99=110ms | TP99=170ms |
5000qps | TP99=140ms | TP99=220ms | TP99=360ms |
再結合上下游接口超時要求,最終確定size可取的最大值為1500左右(不同業務需要結合實際使用的ES集群配置、索引結構以及查詢語句進行實際測試)。但是,面對區域內動輒上千的門店覆蓋,召回1500個商品顯然無法滿足業務需要。
對此,我們采取了一個折中邏輯,將全部門店等量拆分為多組(以下圖為例,每個group包含m個門店),每組門店單獨進行一次ES查詢,size設置為1500。雖然1500的召回量不足以覆蓋所有門店的全部相關商品,但對于一組門店還是相對充足的。通過調整門店分組大小可以對召回率和ES負載進行平衡,在到家搜索的實踐場景中,采取的是30個門店一組。
在有了完整召回能力后,下一步優化的重點就是建立對全量召回結果的排序能力,我們的具體做法如下:
首先,將排序邏輯與搜索核心服務解耦,抽象后獨立部署維護,以便后期排序邏輯的頻繁迭代不會對搜索召回模塊造成影響。
其次,引入大量業務特征,例如促銷、價格、銷量、復購等,并將ES返回的bm25評分作為其中一項特征,通過所有特征加權分來進行排序。這種排序方式簡單有效,在早期時候也取得了不小的收益。
最后,在此基礎上引入了LR線性模型,通過LR模型來計算權重w取值,排序效果又進一步得到了提升。
到家在這個時期無論業務體量還是用戶體量相比最初均有了幾何倍數增長,所以解決單點依賴風險保障服務的高可用性也同樣十分迫切。
從宏觀鏈路上看,整個搜索服務中最薄弱的環節就是底層索引。雖然ES采用了高可用的分布式節點部署、主副分片自動平衡等優秀的架構設計,但在極端情況下依然會有集群異常情況產生,例如ES集群由網絡異常引起的腦裂問題、主副分片節點同時宕機問題等。
所以,建立索引層容災能力才是搜索系統穩定性的關鍵,常見的做法有以下幾種:
1. ES節點跨機房異地部署
描述:將ES集群中不同節點部署在不同機房,降低單機房網絡或故障導致集群不可用的風險。
優點:實現簡單、無需額外操作、索引文件一定無法橫向擴展。
缺點:需要解決跨機房網絡訪問延遲問題,集群存在腦裂風險增加。
2. 定期快照
描述:定期對ES索引生成快照,并將快照數據備份到外部存儲。備份的數據可以在備集群中恢復。
優點:如果集群宕機,可以通過快照文件將數據恢復到其他備用集群,保證主要數據不會丟失。
缺點:部分增量數據丟失、恢復時間長、無法提供集群的橫向擴展能力。
3. 集群雙寫
描述:在上層寫入應用中將索引數據雙寫到兩(多)個集群中,多個集群數據保持一致。
優點:由雙集群保證高可用,異常概率大大降低。還可以借助上層路由策略,對請求流量在集群間分流,做到真正意義上高擴展。
缺點:多集群數據難以保證絕對一致;硬件資源成本成倍增加;多集群使用需要增加路由邏輯控制。
在到家的搜索應用場景中,我們更在意的是服務穩定性以及故障短時間恢復能力,所以最終采用了異地部署加集群雙寫的綜合方案。底層索引由兩套ES集群支撐,所有ES節點分布在兩個機房部署。上層服務雙寫保證索引數據的準一致。
在應用服務內部使用Supplier的方式對ES連接進行管理,再通過外部Zookeeper進行集群路由配置的存儲和通知。當需要修改路由配置時可在Zookeeper中進行調整,由Zookeeper通知所有應用服務實例。具體如下圖所示:
通過一系列優化改造,搜索召回能力得到極大提升,漏召回現象明顯減少。排序方面借助線性模型對召回集合整體排序,也做到了將高質量、高銷量類型商品排在前邊。但是此時整體召排結構和業內高水準架構設計相比還是有不小差距,很快又遇到了新的痛點:
召回策略單一所有Query均使用統一分詞匹配+品牌分類提權的方式召回,在召回策略控制上過于單一。不同Query在語義上強調的重點不同,很難通過一套策略適配所有Query。
線性排序模型瓶頸雖然線性模型排序結果相比1.0版本上有了很大的提升,但線性模型也存在一些天然的弊端。例如需要對特征歸一化處理,O2O場景非標品比例較高,特征統一歸一效果太差,導致模型效果不及預期。另外線性模型學習交叉特征能力弱,無法表達復雜場景,模型優化天花板較低。
在容災能力上,雖然初步實現了對底層多集群的調度控制,但在實際使用場景中也發現了很多問題,例如:
非平臺化接入方式接入雙集群需要在應用代碼中進行額外開發,代碼侵入嚴重,且能力無法復制。
異常處理需要人工介入發生異常時集群流量無法自動熔斷,需要人工操作集群切換。
雖然到家搜索2.0在召排能力及容災能力上都得到了一定的加強,但也只能算是將1.0版本的“可用”水平提升到了“易用”水平,距離“好用”的水平還有著不小的距離。
3.0版本的搜索系統優化目標上主要分成策略和架構兩個部分。
策略上,需要在保證召回率的同時限制錯召過召問題,對召回結果需要建立一套更完善的排序策略,使排序結果更加合理,整體流量分發更加高效。
架構上,期望打造一個高性能、高可用、高擴展的搜索系統,進一步增強底層容災能力,提升系統橫向擴展能力。
為此,提出了以下幾點優化方向:
細分query類型,差異化多路召回
迭代排序模型,提升排序效果
集群路由控制平臺化,異常自動熔斷
在之前的版本中,搜索主要的索引匹配邏輯是通過Query對ES中Sku名稱進行分詞查詢。但如果底層分詞策略調整導致分詞字典發生變化,那么就需要對整個索引進行重建才能生效,十分不靈活。另外一些隱藏的商品屬性在Sku的名稱中可能并不存在,導致無法與Query匹配,這也會引起一系列的漏召問題。
為了提升召回匹配相關性,我們在離線對商品的名稱、品牌、分類、屬性、聚類主題等進行多維度成分提取,將提取出來的數據作為召回通道存儲在ES中。同時對實時請求的Query也做類似的成分提取。在召回時,我們將原來分詞匹配方式改為了Query與Sku之間的成分匹配,通過不同成分信息間的組合限制方式保證了召回的相關性。
另外,為了能實現針對不同類型Query靈活制定召回策略,我們將Query按照組成成分結構劃分成了多種類型,并且針對每一種Query類型都分別制定不同的三級召回策略(以下簡稱L1,L2,L3)。三級召回策略定位不同,
L1精準意圖召回:必須保證Sku與Query成分完全匹配
L2意圖擴展召回:犧牲部分非核心成分匹配限定,但對品類這種核心成分保持了限定,用于擴充召回豐富度
L3補充召回:文本分詞匹配,不做成分限定
不同類型下具體三級召回策略均不相同,在語義相關性限制力度上依次遞減,L1 > L2 > L3。
在召回階段,將三級召回策略與2.0版本引入的門店分組召回方式相結合,每組門店分別進行三次策略召回。在3.0版本中對門店分組策略也進行了優化,原來按數量等分的方式可能會將多個供給充足的門店分到同一組中,這樣在面對召回范圍寬泛的搜索詞時就會發生召回截取,導致召回率降低。所以,在處理分店分組階段,我們結合了門店的靜態供給數量、行業類型對門店分組打散處理,將同行業中供給量充足的門店分配到不同組中,降低召回截取概率,進一步提升了召回率。
在系統架構上,將意圖識別模塊、召回模塊從原系統中解耦獨立部署。將流程調度以及搜索相關的業務處理邏輯封裝在搜索中臺內部,與意圖服務、召回服務以及排序服務共同組成了搜索的核心模塊,在架構上做到低耦合與高內聚。
在2.0版本中我們嘗試了通過簡單線性模型對搜索結果進行排序優化,并且取得了不錯的效果,但也很快就觸碰到了線性模型的天花板。業務發展到這個時期,通過幾個簡單業務特征結合線性模型的排序方式已經難以滿足業務需要,需要深入挖掘多維度特征甚至交叉特征,結合更復雜的模型對整個排序流程進行重構。
搜索排序的最基本原則是要優先保證與Query相關性更高的商品排到前邊。基于搜索3.0版本在多路召回上的調整,使得召回結果帶有了天然的相關性屬性,并且L1、L2、L3的召回結果在相關性上逐層遞減。但是面向召回的三級分層方式在排序場景下還是顯得粒度過粗,所以在召回三級Level的基礎之上排序內部又將其分為了六層Rank,所有排序邏輯均在Rank層內執行,不同分層的商品不跨層調整,如圖:
在排序流程上,采用了預排、粗排、精排、策略重排這樣的四級排序方式,每級排序邏輯的實現方式各有不同,承載的主要職責也有所不同。
預排:主要用于精選召回商品,將召回后的商品通過召回Level等級和靜態質量分進行預排序,最終選取Top 3000結果進入到粗排階段。
粗排:負責初步篩選召回結果中用戶可能感興趣的商品,盡量讓這類商品排到前邊并有機會進入精排階段。考慮到粗排商品量級較大,實現上我們選擇了性能較好的XGB樹模型。
精排:使用TensorFlow深度模型對粗排結果中的Top 200個Sku進行局部的精細化重排。
策略重排:基于模型排序的結果,根據具體的業務規則,對排序結果進行最終的微調。
在算法模型預測邏輯的架構設計上,采用了模型中臺的方式,將常用模型在其內部進行了封裝,結合配套的模型配置平臺可對模型特征及特征獲取方式進行配置化管理。上層排序服務可通過預先在配置平臺設置的modelTag對模型中臺發起預測請求。具體的模型實現邏輯對外部無感知。
為了解決2.0版本中的多集群管理方面的遺留問題,在3.0版本中對底層的集群路由方案也做了全面升級,具體如下圖:
首先,為了簡化接入流程,將原來應用服務內部代碼侵入的管理方式改為了路由管理客戶端接入的方式,路由策略配置交由服務端進行管理,可以做到配置調整實時生效。這樣任何服務均可以通過平臺化的方式接入路由平臺,極大降低了接入成本。
其次,應用服務通過通路由客戶端獲取ES集群連接對象,在執行完成ES請求操作后,路由客戶端會將本次ES操作的成功失敗狀態上報到路由服務端。參考熔斷器的設計思想,由服務端對上報信息進行定時匯總統計,如果發現近一個時間窗口內ES的異常請求操作比例觸發了熔斷閾值,服務端就會通過主動修改路由配置策略屏蔽該集群的路由訪問,并將修改結果廣播通知到客戶端。
最后,在路由平臺的設計上還兼容了多套集群(超過兩套以上)災備的問題,任何接入方均可根據需要靈活配置。
具體路由客戶端和服務端交互方式如下圖所示:
路由客戶端內部實現了對所有集群路由規則邏輯的封裝,對外部黑盒處理。具體的路由策略配置交給路由服務端管理。搜索服務接入路由平臺后,可實時通過路由客戶端提供的ES路由查詢功能來獲取ES客戶端代理。完成與ES的請求交互后,客戶端代理會將請求的成功失敗狀態通過隊列+異步的方式自動上報到服務端,用于ES集群狀態監控。
經過長期迭代,當前的到家搜索系統從宏觀架構上看可以被分為如下幾個模塊:搜索業務模塊、搜索核心模塊、算法模型預測模塊、索引數據模塊、輔助功能模塊。如下圖所示:
搜索業務模塊:承接來自前端所有搜索業務相關請求,是搜索服務的最上層出口。向下與搜索中臺對接,獲取搜索相關業務數據,并根據業務場景需要補全所需數據,結構化封裝后返回給前端。起著承上啟下的作用。
搜索核心模塊:搜索核心模塊由搜索中臺、意圖識別、搜索召回、搜索業務排序幾個服務組成,是整個搜索架構中最重要的組成部分。
算法模型預測模塊:以模型預測中臺服務為統一出口,將常用的模型預測算法進行了統一封裝,對接了例如LR、XGB、Tensorflow等算法模型,提供了多樣化的算法預測能力。在搜索服務鏈路中,模型預測模塊主要承擔著計算搜索結果排序分的作用。
索引數據模塊:到家搜索系統底層索引數據由兩套ES集群支持,兩套集群中索引數據內容相同,由索引構建服務負責對兩套ES進行索引全量構建以及增量更新。兩套集群既可以獨立承接線上流量互為主備,又可以同時承接峰值流量進行壓力分流。
輔助功能模塊:結合研發、測試、運營人員的使用需求,在搜索平臺中提供了搜索結果Debug解釋、搜索策略Diff分析、搜索結果badcase干預、搜索字典動態管理配置等實用功能,極大提升了相關人員的工作效率。
從3.0版本的宏觀架構上看,我們將搜索這樣的復雜業務按領域驅動設計思想進行了系統拆分,每個子系統負責專屬業務功能,系統間設立邊界隔離,系統內部根據業務特性進行垂直化建設,整體模塊劃分已相對清晰。但是從細節邏輯的處理方式上看仍然存在著較多的問題,需要我們在未來的工作中繼續完善,例如:
L3補充召回合理性
隨著L1L2策略日趨完善,L3使用的文本召回的方式已經很難對L1L2進行有效的召回補充,補充的商品大多數相關性較差。
模型維護效率低下
目前模型數量相對可控,模型的訓練、更新等操作主要依靠人工完成。在未來模型越來越多的情況下,維護效率難以保證。
欠缺垂類場景專屬策略
同樣的Query在不同垂類場景下會有不同的意圖含義。例如“蘋果”在生鮮場景下是水果意圖,但在3C場景下卻是手機意圖。建立不同垂類場景的個性化召排策略也是未來優化工作的一個主要方向。
系統優化永遠沒有終點,目前我們已經開始著手準備到家搜索4.0版本的優化工作。在下一個版本中,針對遺留問題有以下幾個重點優化方向:
向量召回:萬物皆可embedding,使用向量召回方式替代現有的L3策略對召回結果進行補充。
自動化模型迭代:構建一個強大的算法平臺,通過任務托管的方式將模型訓練及上線工作自動化運行,避免因為樣本過時導致的模型效果衰減,也可以提高模型的管理效率。
場景化召排策略:針對不同的上層業務入口或者垂類意圖,制定差異化的召排策略,挖掘搜索潛力。
經過幾個版本的優化,到家搜索系統在逐漸地向“好用”水平看齊。在這個過程中我們也深刻體會到“召回決定搜索的下限,排序決定搜索的上限”,二者相輔相成,是搜索系統最重要的兩大核心能力。在未來的工作中,我們依然會堅持以提升用戶搜索體驗為最終目標,圍繞召回、排序兩大搜索核心能力不斷迭代。
美國對中國商品加征10%關稅,對跨境電商的巨大沖擊
759 閱讀SCOR模型:數字化時代供應鏈管理的航海圖
626 閱讀白犀牛副總裁王瀚基:無人配送帶來了哪些機遇與挑戰?
554 閱讀快遞人2025愿望清單:漲派費、少罰款、交社保......
585 閱讀暖心護航春節返程,順豐確保每一份滿滿當當的心意與牽掛新鮮抵達!
420 閱讀1月27日-2月2日全國物流保通保暢運行情況
377 閱讀2025年1月20日-1月26日全國物流保通保暢運行情況
324 閱讀春節假期全國攬投快遞包裹超19億件
334 閱讀京東物流北京區25年331大件DC承運商招標
348 閱讀